f6263965322cd6d394b66b6c02145f3be97a289c
[Packages/TYPO3.CMS.git] / typo3 / class.db_list_extra.inc
1 <?php
2 /*************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2009 Kasper Skaarhoj (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 * Include file extending recordList which extended t3lib_recordList
29 * Used specifically for the Web>List module (db_list.php)
30 *
31 * $Id$
32 * Revised for TYPO3 3.6 December/2003 by Kasper Skaarhoj
33 * XHTML compliant
34 *
35 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
36 */
37 /**
38 * [CLASS/FUNCTION INDEX of SCRIPT]
39 *
40 *
41 *
42 * 91: class localRecordList extends recordList
43 * 123: function writeTop($row)
44 * 304: function getTable($table,$id,$rowlist)
45 * 559: function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0)
46 * 648: function renderListHeader($table,$currentIdList)
47 *
48 * SECTION: Rendering of various elements
49 * 796: function makeControl($table,$row)
50 * 986: function makeClip($table,$row)
51 * 1057: function makeRef($table,$uid)
52 * 1086: function makeLocalizationPanel($table,$row)
53 * 1148: function fieldSelectBox($table,$formFields=1)
54 *
55 * SECTION: Helper functions
56 * 1231: function linkClipboardHeaderIcon($string,$table,$cmd,$warning='')
57 * 1242: function clipNumPane()
58 * 1256: function addSortLink($code,$field,$table)
59 * 1281: function recPath($pid)
60 * 1294: function showNewRecLink($table)
61 * 1304: function makeReturnUrl()
62 *
63 * SECTION: CSV related functions
64 * 1329: function initCSV()
65 * 1352: function addToCSV($row,$table)
66 * 1376: function setCsvRow($csvRow)
67 * 1387: function outputCSV($prefix)
68 *
69 * TOTAL FUNCTIONS: 19
70 * (This index is automatically created/updated by the extension "extdeveval")
71 *
72 */
73
74
75
76
77
78
79
80
81
82
83 /**
84 * Class for rendering of Web>List module
85 *
86 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
87 * @package TYPO3
88 * @subpackage core
89 */
90 class localRecordList extends recordList {
91
92 // External:
93 var $alternateBgColors=FALSE; // If true, table rows in the list will alternate in background colors (and have background colors at all!)
94 var $allowedNewTables=array(); // Used to indicate which tables (values in the array) that can have a create-new-record link. If the array is empty, all tables are allowed.
95 var $deniedNewTables=array(); // Used to indicate which tables (values in the array) that cannot have a create-new-record link. If the array is empty, all tables are allowed.
96 var $newWizards=FALSE; // If true, the control panel will contain links to the create-new wizards for pages and tt_content elements (normally, the link goes to just creating a new element without the wizards!).
97
98 var $dontShowClipControlPanels=FALSE; // If true, will disable the rendering of clipboard + control panels.
99 var $showClipboard=FALSE; // If true, will show the clipboard in the field list.
100 var $noControlPanels = FALSE; // If true, will DISABLE all control panels in lists. (Takes precedence)
101 var $clickMenuEnabled = TRUE; // If true, clickmenus will be rendered
102
103 var $totalRowCount; // count of record rows in view
104
105 var $spaceIcon; // space icon used for alignment
106
107 // Internal:
108 var $pageRow=array(); // Set to the page record (see writeTop())
109
110 var $csvLines=array(); // Used to accumulate CSV lines in for CSV export.
111 var $csvOutput=FALSE; // If set, the listing is returned as CSV instead.
112
113 /**
114 * Clipboard object
115 *
116 * @var t3lib_clipboard
117 */
118 var $clipObj;
119 var $CBnames=array(); // Tracking names of elements (for clipboard use)
120 var $duplicateStack=array(); // Used to track which elements has duplicates and how many
121
122 var $references; // References of the current record
123 var $translations; // Translations of the current record
124 var $selFieldList; // select fields for the query which fetches the translations of the current record
125
126 public function __construct() {
127 parent::__construct();
128 }
129
130 /**
131 * Create the panel of buttons for submitting the form or otherwise perform operations.
132 *
133 * @return array all available buttons as an assoc. array
134 */
135 public function getButtons() {
136 global $LANG;
137
138 $buttons = array(
139 'csh' => '',
140 'view' => '',
141 'edit' => '',
142 'hide_unhide' => '',
143 'move' => '',
144 'new_record' => '',
145 'paste' => '',
146 'level_up' => '',
147 'cache' => '',
148 'reload' => '',
149 'shortcut' => '',
150 'back' => '',
151 'csv' => '',
152 'export' => ''
153 );
154
155 // Get users permissions for this page record:
156 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms($this->pageRow);
157
158 // CSH
159 if (!strlen($this->id)) {
160 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_noId', $GLOBALS['BACK_PATH'], '', TRUE);
161 } elseif(!$this->id) {
162 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_root', $GLOBALS['BACK_PATH'], '', TRUE);
163 } else {
164 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module', $GLOBALS['BACK_PATH'], '', TRUE);
165 }
166
167 if (isset($this->id)) {
168 // View Exclude doktypes 254,255 Configuration: mod.web_list.noViewWithDokTypes = 254,255
169 if (isset($GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'])) {
170 $noViewDokTypes = t3lib_div::trimExplode(',', $GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'], true);
171 } else {
172 //default exclusion: doktype 254, 255
173 $noViewDokTypes = array('254', '255');
174 }
175
176 if (!in_array($this->pageRow['doktype'], $noViewDokTypes)) {
177 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewOnClick($this->id, $this->backPath, t3lib_BEfunc::BEgetRootLine($this->id))) . '">' .
178 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/zoom.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', 1) . '" alt="" />' .
179 '</a>';
180 }
181
182 // New record
183 if (!$GLOBALS['SOBE']->modTSconfig['properties']['noCreateRecordsLink']) {
184 $buttons['new_record'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'db_new.php?id=' . $this->id . '\');') . '">' .
185 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/new_el.gif') . ' title="' . $LANG->getLL('newRecordGeneral', 1) . '" alt="" />' .
186 '</a>';
187 }
188
189 // If edit permissions are set (see class.t3lib_userauthgroup.php)
190 if ($localCalcPerms&2 && !empty($this->id)) {
191
192 // Edit
193 $params = '&edit[pages][' . $this->pageRow['uid'] . ']=edit';
194 $buttons['edit'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) . '">' .
195 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/edit2.gif') . ' title="' . $LANG->getLL('editPage', 1) . '" alt="" />' .
196 '</a>';
197 // Unhide
198 if ($this->pageRow['hidden']) {
199 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=0';
200 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '">' .
201 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/button_unhide.gif') . ' title="' . $LANG->getLL('unHidePage', 1) . '" alt="" />' .
202 '</a>';
203 // Hide
204 } else {
205 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=1';
206 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '">'.
207 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/button_hide.gif') . ' title="' . $LANG->getLL('hidePage', 1) . '" alt="" />' .
208 '</a>';
209 }
210
211 // Move
212 $buttons['move'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'move_el.php?table=pages&uid=' . $this->pageRow['uid'] . '\');') . '">' .
213 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/move_' . ($this->table == 'tt_content' ? 'record' : 'page') . '.gif') . ' title="' . $LANG->getLL('move_page', 1) . '" alt="" />' .
214 '</a>';
215
216 // Up one level
217 $buttons['level_up'] = '<a href="' . htmlspecialchars($this->listURL($this->pageRow['pid'])) . '" onclick="setHighlight(' . $this->pageRow['pid'] . ')">' .
218 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/i/pages_up.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.upOneLevel', 1) . '" alt="" />' .
219 '</a>';
220
221 }
222
223
224 // Paste
225 if (($localCalcPerms&8) || ($localCalcPerms&16)) {
226 $elFromTable = $this->clipObj->elFromTable('');
227 if (count($elFromTable)) {
228 $buttons['paste'] = '<a href="' . htmlspecialchars($this->clipObj->pasteUrl('', $this->id)) . '" onclick="' . htmlspecialchars('return ' . $this->clipObj->confirmMsg('pages', $this->pageRow, 'into', $elFromTable)) . '">' .
229 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clip_pasteafter.gif') . ' title="' . $LANG->getLL('clip_paste', 1) . '" alt="" />' .
230 '</a>';
231 }
232 }
233
234 // Cache
235 $buttons['cache'] = '<a href="' . htmlspecialchars($this->listURL() . '&clear_cache=1') . '">' .
236 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clear_cache.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.clear_cache', 1) . '" alt="" />' .
237 '</a>';
238
239 if ($this->table) {
240
241 // CSV
242 $buttons['csv'] = '<a href="' . htmlspecialchars($this->listURL() . '&csv=1') . '">' .
243 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/csv.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.csv', 1) . '" alt="" />' .
244 '</a>';
245
246 // Export
247 if (t3lib_extMgm::isLoaded('impexp')) {
248 $buttons['export'] = '<a href="' . htmlspecialchars($this->backPath. 'mod.php?M=xMOD_tximpexp&tx_impexp[action]=export&tx_impexp[list][]=' . rawurlencode($this->table . ':' . $this->id)) . '">' .
249 '<img' . t3lib_iconWorks::skinImg($this->backPath, t3lib_extMgm::extRelPath('impexp') . 'export.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:rm.export', 1) . '" alt="" />' .
250 '</a>';
251 }
252
253 }
254
255 // Reload
256 $buttons['reload'] = '<a href="' . htmlspecialchars($this->listURL()) . '">' .
257 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/refresh_n.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.reload', 1) . '" alt="" />' .
258 '</a>';
259
260 // Shortcut
261 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
262 $buttons['shortcut'] = $GLOBALS['TBE_TEMPLATE']->makeShortcutIcon('id, imagemode, pointer, table, search_field, search_levels, showLimit, sortField, sortRev', implode(',', array_keys($this->MOD_MENU)), 'web_list');
263 }
264
265 // Back
266 if ($this->returnUrl) {
267 $buttons['back'] = '<a href="' . htmlspecialchars(t3lib_div::linkThisUrl($this->returnUrl, array('id' => $this->id))) . '" class="typo3-goBack">' .
268 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/goback.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.goBack', 1) . '" alt="" />' .
269 '</a>';
270 }
271 }
272
273 return $buttons;
274 }
275
276 /**
277 * Creates the listing of records from a single table
278 *
279 * @param string Table name
280 * @param integer Page id
281 * @param string List of fields to show in the listing. Pseudo fields will be added including the record header.
282 * @return string HTML table with the listing for the record.
283 */
284 function getTable($table,$id,$rowlist) {
285 global $TCA, $TYPO3_CONF_VARS;
286
287 // Loading all TCA details for this table:
288 t3lib_div::loadTCA($table);
289
290 // Init
291 $addWhere = '';
292 $titleCol = $TCA[$table]['ctrl']['label'];
293 $thumbsCol = $TCA[$table]['ctrl']['thumbnail'];
294 $l10nEnabled = $TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField'] && !$TCA[$table]['ctrl']['transOrigPointerTable'];
295 $tableCollapsed = (!$this->tablesCollapsed[$table]) ? false : true;
296
297 // prepare space icon
298 $iconWidth = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeWidth'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeWidth'] : 12;
299 $iconHeight = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeHeight'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeHeight'] : 12;
300 $this->spaceIcon = '<img src="' . $this->backPath . 'clear.gif" width="' . $iconWidth . '" height="' . $iconHeight . '" title="" alt="" />';
301
302 // Cleaning rowlist for duplicates and place the $titleCol as the first column always!
303 $this->fieldArray=array();
304 // title Column
305 $this->fieldArray[] = $titleCol; // Add title column
306 // Control-Panel
307 if (!t3lib_div::inList($rowlist,'_CONTROL_')) {
308 $this->fieldArray[] = '_CONTROL_';
309 $this->fieldArray[] = '_AFTERCONTROL_';
310 }
311 // Clipboard
312 if ($this->showClipboard) {
313 $this->fieldArray[] = '_CLIPBOARD_';
314 }
315 // Ref
316 if (!$this->dontShowClipControlPanels) {
317 $this->fieldArray[]='_REF_';
318 $this->fieldArray[]='_AFTERREF_';
319 }
320 // Path
321 if ($this->searchLevels) {
322 $this->fieldArray[]='_PATH_';
323 }
324 // Localization
325 if ($this->localizationView && $l10nEnabled) {
326 $this->fieldArray[] = '_LOCALIZATION_';
327 $this->fieldArray[] = '_LOCALIZATION_b';
328 $addWhere.=' AND (
329 '.$TCA[$table]['ctrl']['languageField'].'<=0
330 OR
331 '.$TCA[$table]['ctrl']['transOrigPointerField'].' = 0
332 )';
333 }
334 // Cleaning up:
335 $this->fieldArray=array_unique(array_merge($this->fieldArray,t3lib_div::trimExplode(',',$rowlist,1)));
336 if ($this->noControlPanels) {
337 $tempArray = array_flip($this->fieldArray);
338 unset($tempArray['_CONTROL_']);
339 unset($tempArray['_CLIPBOARD_']);
340 $this->fieldArray = array_keys($tempArray);
341 }
342
343 // Creating the list of fields to include in the SQL query:
344 $selectFields = $this->fieldArray;
345 $selectFields[] = 'uid';
346 $selectFields[] = 'pid';
347 if ($thumbsCol) $selectFields[] = $thumbsCol; // adding column for thumbnails
348 if ($table=='pages') {
349 if (t3lib_extMgm::isLoaded('cms')) {
350 $selectFields[] = 'module';
351 $selectFields[] = 'extendToSubpages';
352 $selectFields[] = 'nav_hide';
353 }
354 $selectFields[] = 'doktype';
355 }
356 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) {
357 $selectFields = array_merge($selectFields,$TCA[$table]['ctrl']['enablecolumns']);
358 }
359 if ($TCA[$table]['ctrl']['type']) {
360 $selectFields[] = $TCA[$table]['ctrl']['type'];
361 }
362 if ($TCA[$table]['ctrl']['typeicon_column']) {
363 $selectFields[] = $TCA[$table]['ctrl']['typeicon_column'];
364 }
365 if ($TCA[$table]['ctrl']['versioningWS']) {
366 $selectFields[] = 't3ver_id';
367 $selectFields[] = 't3ver_state';
368 $selectFields[] = 't3ver_wsid';
369 $selectFields[] = 't3ver_swapmode'; // Filtered out when pages in makeFieldList()
370 }
371 if ($l10nEnabled) {
372 $selectFields[] = $TCA[$table]['ctrl']['languageField'];
373 $selectFields[] = $TCA[$table]['ctrl']['transOrigPointerField'];
374 }
375 if ($TCA[$table]['ctrl']['label_alt']) {
376 $selectFields = array_merge($selectFields,t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['label_alt'],1));
377 }
378 $selectFields = array_unique($selectFields); // Unique list!
379 $selectFields = array_intersect($selectFields,$this->makeFieldList($table,1)); // Making sure that the fields in the field-list ARE in the field-list from TCA!
380 $selFieldList = implode(',',$selectFields); // implode it into a list of fields for the SQL-statement.
381 $this->selFieldList = $selFieldList;
382
383 /**
384 * @hook DB-List getTable
385 * @date 2007-11-16
386 * @request Malte Jansen <mail@maltejansen.de>
387 */
388 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) {
389 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) {
390 $hookObject = &t3lib_div::getUserObj($classData);
391
392 if(!($hookObject instanceof t3lib_localRecordListGetTableHook)) {
393 throw new UnexpectedValueException('$hookObject must implement interface t3lib_localRecordListGetTableHook', 1195114460);
394 }
395
396 $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this);
397 }
398 }
399
400 // Create the SQL query for selecting the elements in the listing:
401 if ($this->csvOutput) { // do not do paging when outputting as CSV
402 $this->iLimit = 0;
403 }
404
405 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
406 // Get the two previous rows for sorting if displaying page > 1
407 $this->firstElementNumber = $this->firstElementNumber - 2;
408 $this->iLimit = $this->iLimit + 2;
409 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc)
410 $this->firstElementNumber = $this->firstElementNumber + 2;
411 $this->iLimit = $this->iLimit - 2;
412 } else {
413 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc)
414 }
415
416 $this->setTotalItems($queryParts); // Finding the total amount of records on the page (API function from class.db_list.inc)
417
418 // Init:
419 $dbCount = 0;
420 $out = '';
421 $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table;
422
423 // If the count query returned any number of records, we perform the real query, selecting records.
424 if ($this->totalItems) {
425 // Fetch records only if not in single table mode or if in multi table mode and not collapsed
426 if ($listOnlyInSingleTableMode || (!$this->table && $tableCollapsed)) {
427 $dbCount = $this->totalItems;
428 } else {
429 // set the showLimit to the number of records when outputting as CSV
430 if ($this->csvOutput) {
431 $this->showLimit = $this->totalItems;
432 $this->iLimit = $this->totalItems;
433 }
434 $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
435 $dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result);
436 }
437 }
438
439 // If any records was selected, render the list:
440 if ($dbCount) {
441
442 // Half line is drawn between tables:
443 if (!$listOnlyInSingleTableMode) {
444 $theData = Array();
445 if (!$this->table && !$rowlist) {
446 $theData[$titleCol] = '<img src="clear.gif" width="'.($GLOBALS['SOBE']->MOD_SETTINGS['bigControlPanel']?'230':'350').'" height="1" alt="" />';
447 if (in_array('_CONTROL_',$this->fieldArray)) $theData['_CONTROL_']='';
448 if (in_array('_CLIPBOARD_',$this->fieldArray)) $theData['_CLIPBOARD_']='';
449 }
450 $out.=$this->addelement(0,'',$theData,'class="c-table-row-spacer"',$this->leftMargin);
451 }
452
453 // Header line is drawn
454 $theData = Array();
455 if ($this->disableSingleTableView) {
456 $theData[$titleCol] = '<span class="c-table">'.$GLOBALS['LANG']->sL($TCA[$table]['ctrl']['title'],1).'</span> ('.$this->totalItems.')';
457 } else {
458 $theData[$titleCol] = $this->linkWrapTable($table,'<span class="c-table">'.$GLOBALS['LANG']->sL($TCA[$table]['ctrl']['title'],1).'</span> ('.$this->totalItems.') <img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/'.($this->table?'minus':'plus').'bullet_list.gif','width="18" height="12"').' hspace="10" class="absmiddle" title="'.$GLOBALS['LANG']->getLL(!$this->table?'expandView':'contractView',1).'" alt="" />');
459 }
460
461 // CSH:
462 $theData[$titleCol].= t3lib_BEfunc::cshItem($table,'',$this->backPath,'',FALSE,'margin-bottom:0px; white-space: normal;');
463
464 if ($listOnlyInSingleTableMode) {
465 $out.='
466 <tr>
467 <td class="c-headLineTable" style="width:95%;">'.$theData[$titleCol].'</td>
468 </tr>';
469
470 if ($GLOBALS['BE_USER']->uc["edit_showFieldHelp"]) {
471 $GLOBALS['LANG']->loadSingleTableDescription($table);
472 if (isset($GLOBALS['TCA_DESCR'][$table]['columns'][''])) {
473 $onClick = 'vHWin=window.open(\'view_help.php?tfID='.$table.'.\',\'viewFieldHelp\',\'height=400,width=600,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;';
474 $out.='
475 <tr>
476 <td class="c-tableDescription">'.t3lib_BEfunc::helpTextIcon($table,'',$this->backPath,TRUE).$GLOBALS['TCA_DESCR'][$table]['columns']['']['description'].'</td>
477 </tr>';
478 }
479 }
480 } else {
481 // Render collapse button if in multi table mode
482 $collapseIcon = '';
483 if (!$this->table) {
484 $collapseIcon = '<a href="' . htmlspecialchars($this->listURL()) . '&collapse[' . $table . ']=' . ($tableCollapsed ? '0' : '1') . '"><img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/arrow' . ($tableCollapsed ? 'right' : 'down') . '.png') . ' class="collapseIcon" alt="" title="' . ($tableCollapsed ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.expandTable',1) : $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.collapseTable',1)) . '" /></a>';
485 }
486 $out .= $this->addelement(1, $collapseIcon, $theData, ' class="c-headLineTable"', '');
487 }
488
489 // Render table rows only if in multi table view and not collapsed or if in single table view
490 if (!$listOnlyInSingleTableMode && (!$tableCollapsed || $this->table)) {
491 // Fixing a order table for sortby tables
492 $this->currentTable = array();
493 $currentIdList = array();
494 $doSort = ($TCA[$table]['ctrl']['sortby'] && !$this->sortField);
495
496 $prevUid = 0;
497 $prevPrevUid = 0;
498
499 // Get first two rows and initialize prevPrevUid and prevUid if on page > 1
500 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
501 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
502 $prevPrevUid = -(int) $row['uid'];
503 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
504 $prevUid = $row['uid'];
505 }
506
507 $accRows = array(); // Accumulate rows here
508 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
509
510 // In offline workspace, look for alternative record:
511 t3lib_BEfunc::workspaceOL($table, $row, $GLOBALS['BE_USER']->workspace, TRUE);
512
513 if (is_array($row)) {
514 $accRows[] = $row;
515 $currentIdList[] = $row['uid'];
516 if ($doSort) {
517 if ($prevUid) {
518 $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
519 $this->currentTable['next'][$prevUid] = '-'.$row['uid'];
520 $this->currentTable['prevUid'][$row['uid']] = $prevUid;
521 }
522 $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
523 $prevUid=$row['uid'];
524 }
525 }
526 }
527 $GLOBALS['TYPO3_DB']->sql_free_result($result);
528
529 $this->totalRowCount = count($accRows);
530
531 // CSV initiated
532 if ($this->csvOutput) $this->initCSV();
533
534 // Render items:
535 $this->CBnames=array();
536 $this->duplicateStack=array();
537 $this->eCounter=$this->firstElementNumber;
538
539 $iOut = '';
540 $cc = 0;
541
542 foreach($accRows as $row) {
543 // Render item row if counter < limit
544 if ($cc < $this->iLimit) {
545 $cc++;
546 $this->translations = FALSE;
547 $iOut.= $this->renderListRow($table,$row,$cc,$titleCol,$thumbsCol);
548
549 // If localization view is enabled it means that the selected records are either default or All language and here we will not select translations which point to the main record:
550 if ($this->localizationView && $l10nEnabled) {
551 // For each available translation, render the record:
552 if (is_array($this->translations)) {
553 foreach ($this->translations as $lRow) {
554 // In offline workspace, look for alternative record:
555 t3lib_BEfunc::workspaceOL($table, $lRow, $GLOBALS['BE_USER']->workspace);
556 if (is_array($lRow) && $GLOBALS['BE_USER']->checkLanguageAccess($lRow[$TCA[$table]['ctrl']['languageField']])) {
557 $currentIdList[] = $lRow['uid'];
558 $iOut.=$this->renderListRow($table,$lRow,$cc,$titleCol,$thumbsCol,18);
559 }
560 }
561 }
562 }
563 }
564
565 // Counter of total rows incremented:
566 $this->eCounter++;
567 }
568
569 // Record navigation is added to the beginning and end of the table if in single table mode
570 if ($this->table) {
571 $pageNavigation = $this->renderListNavigation();
572 $iOut = $pageNavigation . $iOut . $pageNavigation;
573 }
574
575 // The header row for the table is now created:
576 $out.=$this->renderListHeader($table,$currentIdList);
577 }
578
579 // The list of records is added after the header:
580 $out.=$iOut;
581 unset($iOut);
582
583 // ... and it is all wrapped in a table:
584 $out='
585
586
587
588 <!--
589 DB listing of elements: "'.htmlspecialchars($table).'"
590 -->
591 <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist'.($listOnlyInSingleTableMode?' typo3-dblist-overview':'').'">
592 '.$out.'
593 </table>';
594
595 // Output csv if...
596 if ($this->csvOutput) $this->outputCSV($table); // This ends the page with exit.
597 }
598
599 // Return content:
600 return $out;
601 }
602
603 /**
604 * Rendering a single row for the list
605 *
606 * @param string Table name
607 * @param array Current record
608 * @param integer Counter, counting for each time an element is rendered (used for alternating colors)
609 * @param string Table field (column) where header value is found
610 * @param string Table field (column) where (possible) thumbnails can be found
611 * @param integer Indent from left.
612 * @return string Table row for the element
613 * @access private
614 * @see getTable()
615 */
616 function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0) {
617 $iOut = '';
618
619 if (strlen($this->searchString)) { // If in search mode, make sure the preview will show the correct page
620 $id_orig = $this->id;
621 $this->id = $row['pid'];
622 }
623
624 if (is_array($row)) {
625
626 $this->setReferences($table, $row['uid']);
627 // add special classes for first and last row
628 $rowSpecial = '';
629 if ($cc == 1 && $indent == 0) {
630 $rowSpecial .= ' firstcol';
631 }
632 if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
633 $rowSpecial .= ' lastcol';
634 }
635
636 // Background color, if any:
637 if ($this->alternateBgColors) {
638 $row_bgColor = ($cc%2) ? ' class="db_list_normal'.$rowSpecial.'"' : ' class="db_list_alt'.$rowSpecial.'"';
639 } else {
640 $row_bgColor = ' class="db_list_normal'.$rowSpecial.'"';
641 }
642 // Overriding with versions background color if any:
643 $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor;
644
645 // Incr. counter.
646 $this->counter++;
647
648 // The icon with link
649 $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table);
650 $iconImg = t3lib_iconWorks::getIconImage($table,$row,$this->backPath,'title="'.htmlspecialchars($alttext).'"'.($indent ? ' style="margin-left: '.$indent.'px;"' : ''));
651 $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg;
652
653 // Preparing and getting the data-array
654 $theData = Array();
655 foreach($this->fieldArray as $fCol) {
656 if ($fCol==$titleCol) {
657 $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
658 // If the record is edit-locked by another user, we will show a little warning sign:
659 if (($lockInfo = t3lib_BEfunc::isRecordLocked($table, $row['uid']))) {
660 $warning = '<a href="#" onclick="' . htmlspecialchars('alert(' . $GLOBALS['LANG']->JScharCode($lockInfo['msg']) . '); return false;') . '">' .
661 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/recordlock_warning3.gif', 'width="17" height="12"') . ' title="' . htmlspecialchars($lockInfo['msg']) . '" alt="" />' .
662 '</a>';
663 }
664 $theData[$fCol] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row);
665
666 $localizationMarkerClass = '';
667 if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField'])
668 && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0) {
669 // it's a translated record
670 $localizationMarkerClass = ' localization';
671 }
672 } elseif ($fCol == 'pid') {
673 $theData[$fCol]=$row[$fCol];
674 } elseif ($fCol == '_PATH_') {
675 $theData[$fCol]=$this->recPath($row['pid']);
676 } elseif ($fCol == '_REF_') {
677 $theData[$fCol]=$this->makeRef($table,$row['uid']);
678 } elseif ($fCol == '_CONTROL_') {
679 $theData[$fCol]=$this->makeControl($table,$row);
680 } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') {
681 $theData[$fCol] = '&nbsp;';
682 } elseif ($fCol == '_CLIPBOARD_') {
683 $theData[$fCol]=$this->makeClip($table,$row);
684 } elseif ($fCol == '_LOCALIZATION_') {
685 list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row);
686 $theData[$fCol] = $lC1;
687 $theData[$fCol.'b'] = $lC2;
688 } elseif ($fCol == '_LOCALIZATION_b') {
689 // Do nothing, has been done above.
690 } else {
691 $tmpProc = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']);
692 $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
693 $row[$fCol] = $tmpProc;
694 }
695 }
696
697 if (strlen($this->searchString)) { // Reset the ID if it was overwritten
698 $this->id = $id_orig;
699 }
700
701 // Add row to CSV list:
702 if ($this->csvOutput) {
703 $this->addToCSV($row,$table);
704 }
705
706 // Add classes to table cells
707 $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass;
708 if (!$this->dontShowClipControlPanels) {
709 $this->addElement_tdCssClass['_CONTROL_'] = 'col-control';
710 $this->addElement_tdCssClass['_AFTERCONTROL_'] = 'col-control-space';
711 $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard';
712 }
713 $this->addElement_tdCssClass['_PATH_'] = 'col-path';
714 $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa';
715 $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb';
716
717
718 // Create element in table cells:
719 $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor);
720
721 // Render thumbsnails if a thumbnail column exists and there is content in it:
722 if ($this->thumbs && trim($row[$thumbsCol])) {
723 $iOut.=$this->addelement(4,'', Array($titleCol=>$this->thumbCode($row,$table,$thumbsCol)),$row_bgColor);
724 }
725
726 // Finally, return table row element:
727 return $iOut;
728 }
729 }
730
731 /**
732 * Write sys_refindex entries for current record to $this->references
733 *
734 * @param string Table name
735 * @param integer Uid of current record
736 * @return void
737 */
738 function setReferences($table, $uid) {
739 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
740 '*',
741 'sys_refindex',
742 'ref_table='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_refindex').
743 ' AND ref_uid='.intval($uid).
744 ' AND deleted=0'
745 );
746 $this->references = $rows;
747 }
748
749 /**
750 * Rendering the header row for a table
751 *
752 * @param string Table name
753 * @param array Array of the currently displayed uids of the table
754 * @return string Header table row
755 * @access private
756 * @see getTable()
757 */
758 function renderListHeader($table, $currentIdList) {
759 global $TCA, $LANG, $TYPO3_CONF_VARS;
760
761 // Init:
762 $theData = Array();
763
764 // Traverse the fields:
765 foreach($this->fieldArray as $fCol) {
766
767 // Calculate users permissions to edit records in the table:
768 $permsEdit = $this->calcPerms & ($table=='pages'?2:16);
769
770 switch((string)$fCol) {
771 case '_PATH_': // Path
772 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._PATH_',1).']</i>';
773 break;
774 case '_REF_': // References
775 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_mod_file_list.xml:c__REF_',1).']</i>';
776 break;
777 case '_LOCALIZATION_': // Path
778 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._LOCALIZATION_',1).']</i>';
779 break;
780 case '_LOCALIZATION_b': // Path
781 $theData[$fCol] = $LANG->getLL('Localize',1);
782 break;
783 case '_CLIPBOARD_': // Clipboard:
784 $cells=array();
785
786 // If there are elements on the clipboard for this table, then display the "paste into" icon:
787 $elFromTable = $this->clipObj->elFromTable($table);
788 if (count($elFromTable)) {
789 $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,$this->id)).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg('pages',$this->pageRow,'into',$elFromTable)).'">'.
790 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_paste',1).'" alt="" />'.
791 '</a>';
792 }
793
794 // If the numeric clipboard pads are enabled, display the control icons for that:
795 if ($this->clipObj->current!='normal') {
796
797 // The "select" link:
798 $cells['copyMarked']=$this->linkClipboardHeaderIcon('<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_copy.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_selectMarked',1).'" alt="" />',$table,'setCB');
799
800 // The "edit marked" link:
801 $editIdList = implode(',',$currentIdList);
802 $editIdList = "'+editList('".$table."','".$editIdList."')+'";
803 $params='&edit['.$table.']['.$editIdList.']=edit&disHelp=1';
804 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
805 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('clip_editMarked',1).'" alt="" />'.
806 '</a>';
807
808 // The "Delete marked" link:
809 $cells['delete']=$this->linkClipboardHeaderIcon('<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$LANG->getLL('clip_deleteMarked',1).'" alt="" />',$table,'delete',sprintf($LANG->getLL('clip_deleteMarkedWarning'),$LANG->sL($TCA[$table]['ctrl']['title'])));
810
811 // The "Select all" link:
812 $cells['markAll']='<a href="#" onclick="'.htmlspecialchars('checkOffCB(\''.implode(',',$this->CBnames).'\'); return false;').'">'.
813 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_select.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_markRecords',1).'" alt="" />'.
814 '</a>';
815 } else {
816 $cells['empty']='';
817 }
818 /**
819 * @hook renderListHeaderActions: Allows to change the clipboard icons of the Web>List table headers
820 * @date 2007-11-20
821 * @request Bernhard Kraft <krafbt@kraftb.at>
822 * @usage Above each listed table in Web>List a header row is shown. This hook allows to modify the icons responsible for the clipboard functions (shown above the clipboard checkboxes when a clipboard other than "Normal" is selected), or other "Action" functions which perform operations on the listed records.
823 */
824 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
825 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
826 $hookObject = &t3lib_div::getUserObj($classData);
827 if(!($hookObject instanceof localRecordList_actionsHook)) {
828 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567850);
829 }
830 $cells = $hookObject->renderListHeaderActions($table, $currentIdList, $cells, $this);
831 }
832 }
833 $theData[$fCol]=implode('',$cells);
834 break;
835 case '_CONTROL_': // Control panel:
836 if (!$TCA[$table]['ctrl']['readOnly']) {
837
838 // If new records can be created on this page, add links:
839 if ($this->calcPerms&($table=='pages'?8:16) && $this->showNewRecLink($table)) {
840 if ($table=="tt_content" && $this->newWizards) {
841 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
842 $tmpTSc = t3lib_BEfunc::getModTSconfig($this->pageinfo['uid'],'mod.web_list');
843 $tmpTSc = $tmpTSc ['properties']['newContentWiz.']['overrideWithExtension'];
844 $newContentWizScriptPath = $this->backPath.t3lib_extMgm::isLoaded($tmpTSc) ? (t3lib_extMgm::extRelPath($tmpTSc).'mod1/db_new_content_el.php') : 'sysext/cms/layout/db_new_content_el.php';
845
846 $icon = '<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$newContentWizScriptPath.'?id='.$this->id.'\');').'">'.
847 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new',1).'" alt="" />'.
848 '</a>';
849 } elseif ($table=='pages' && $this->newWizards) {
850 $icon = '<a href="'.htmlspecialchars($this->backPath.'db_new.php?id='.$this->id.'&pagesOnly=1&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
851 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new',1).'" alt="" />'.
852 '</a>';
853
854 } else {
855 $params = '&edit['.$table.']['.$this->id.']=new';
856 if ($table == 'pages_language_overlay') {
857 $params .= '&overrideVals[pages_language_overlay][doktype]=' . (int) $this->pageRow['doktype'];
858 }
859 $icon = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
860 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new',1).'" alt="" />'.
861 '</a>';
862 }
863 }
864
865 // If the table can be edited, add link for editing ALL SHOWN fields for all listed records:
866 if ($permsEdit && $this->table && is_array($currentIdList)) {
867 $editIdList = implode(',',$currentIdList);
868 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
869 $params = '&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.implode(',',$this->fieldArray).'&disHelp=1';
870 $icon .= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
871 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('editShownColumns',1).'" alt="" />'.
872 '</a>';
873 }
874 // add an empty entry, so column count fits again after moving this into $icon
875 $theData[$fCol] = '&nbsp;';
876 }
877 break;
878 case '_AFTERCONTROL_': // space column
879 case '_AFTERREF_': // space column
880 $theData[$fCol] = '&nbsp;';
881 break;
882 default: // Regular fields header:
883 $theData[$fCol]='';
884 if ($this->table && is_array($currentIdList)) {
885
886 // If the numeric clipboard pads are selected, show duplicate sorting link:
887 if ($this->clipNumPane()) {
888 $theData[$fCol].='<a href="'.htmlspecialchars($this->listURL('',-1).'&duplicateField='.$fCol).'">'.
889 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/select_duplicates.gif','width="11" height="11"').' title="'.$LANG->getLL('clip_duplicates',1).'" alt="" />'.
890 '</a>';
891 }
892
893 // If the table can be edited, add link for editing THIS field for all listed records:
894 if (!$TCA[$table]['ctrl']['readOnly'] && $permsEdit && $TCA[$table]['columns'][$fCol]) {
895 $editIdList = implode(',',$currentIdList);
896 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
897 $params='&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.$fCol.'&disHelp=1';
898 $iTitle = sprintf($LANG->getLL('editThisColumn'),rtrim(trim($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol))),':'));
899 $theData[$fCol].='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
900 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.htmlspecialchars($iTitle).'" alt="" />'.
901 '</a>';
902 }
903 }
904 $theData[$fCol].=$this->addSortLink($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol,'<i>[|]</i>')),$fCol,$table);
905 break;
906 }
907
908 }
909
910 /**
911 * @hook renderListHeader: Allows to change the contents of columns/cells of the Web>List table headers
912 * @date 2007-11-20
913 * @request Bernhard Kraft <krafbt@kraftb.at>
914 * @usage Above each listed table in Web>List a header row is shown. Containing the labels of all shown fields and additional icons to create new records for this table or perform special clipboard tasks like mark and copy all listed records to clipboard, etc.
915 */
916 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
917 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
918 $hookObject = &t3lib_div::getUserObj($classData);
919 if(!($hookObject instanceof localRecordList_actionsHook)) {
920 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567855);
921 }
922 $theData = $hookObject->renderListHeader($table, $currentIdList, $theData, $this);
923 }
924 }
925
926 // Create and return header table row:
927 return $this->addelement(1, $icon, $theData, ' class="c-headLine"', '');
928 }
929
930 /**
931 * Creates a page browser for tables with many records
932 *
933 * @return string Navigation HTML
934 *
935 * @author Dmitry Pikhno <dpi@goldenplanet.com>
936 * @author Christian Kuhn <lolli@schwarzbu.ch>
937 */
938 protected function renderListNavigation() {
939 $totalPages = ceil($this->totalItems / $this->iLimit);
940
941 $content = '';
942
943 // Show page selector if not all records fit into one page
944 if ($totalPages > 1) {
945 $first = $previous = $next = $last = $reload = '';
946 $listURL = $this->listURL('', $this->table);
947
948 // 1 = first page
949 $currentPage = floor(($this->firstElementNumber + 1) / $this->iLimit) + 1;
950
951 // Compile first, previous, next, last and refresh buttons
952 if ($currentPage > 1) {
953 $labelFirst = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:first');
954
955 $first = '<a href="' . $listURL . '&pointer=0">
956 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_first.gif')
957 . 'alt="' . $labelFirst . '" title="' . $labelFirst . '" />
958 </a>';
959 } else {
960 $first = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_first_disabled.gif') . 'alt="" title="" />';
961 }
962
963 if (($currentPage - 1) > 0) {
964 $labelPrevious = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:previous');
965
966 $previous = '<a href="' . $listURL . '&pointer=' . (($currentPage - 2) * $this->iLimit) . '">
967 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_previous.gif')
968 . 'alt="' . $labelPrevious . '" title="' . $labelPrevious . '" />
969 </a>';
970 } else {
971 $previous = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_previous_disabled.gif') . 'alt="" title="" />';
972 }
973
974 if (($currentPage + 1) <= $totalPages) {
975 $labelNext = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:next');
976
977 $next = '<a href="' . $listURL . '&pointer=' . (($currentPage) * $this->iLimit) . '">
978 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_next.gif')
979 . 'alt="' . $labelNext . '" title="' . $labelNext . '" />
980 </a>';
981 } else {
982 $next = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_next_disabled.gif') . 'alt="" title="" />';
983 }
984
985 if ($currentPage != $totalPages) {
986 $labelLast = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:last');
987
988 $last = '<a href="' . $listURL . '&pointer=' . (($totalPages - 1) * $this->iLimit) . '">
989 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_last.gif')
990 . 'alt="' . $labelLast . '" title="' . $labelLast . '" />
991 </a>';
992 } else {
993 $last = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_last_disabled.gif') . 'alt="" title="" />';
994 }
995
996 $reload = '<a href="#" onclick="document.dblistForm.action=\''
997 . $listURL . '&pointer=\'+calculatePointer(); document.dblistForm.submit(); return true;">
998 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/refresh_n.gif')
999 . 'alt="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:reload')
1000 . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:reload')
1001 . '" /></a>';
1002
1003 // Add js to traverse a page select input to a pointer value
1004 $content = '
1005 <script type="text/JavaScript">
1006 /*<![CDATA[*/
1007
1008 function calculatePointer(){
1009 page = document.getElementById(\'jumpPage\').value;
1010
1011 if (page > ' . $totalPages . ') {
1012 page = ' . $totalPages . ';
1013 }
1014
1015 if (page < 1) {
1016 page = 1;
1017 }
1018
1019 pointer = (page - 1) * ' . $this->iLimit . ';
1020
1021 return pointer;
1022 }
1023
1024 /*]]>*/
1025 </script>
1026 ';
1027
1028 $pageNumberInput = '<span>
1029 <input type="text" value="' . $currentPage
1030 . '" size="3" id="jumpPage" name="jumpPage" onkeyup="if (event.keyCode == Event.KEY_RETURN) { document.dblistForm.action=\'' . $listURL . '&pointer=\'+calculatePointer(); document.dblistForm.submit(); } return true;" />
1031 </span>';
1032 $pageIndicator = '<span class="pageIndicator">'
1033 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:pageIndicator'), $pageNumberInput, $totalPages)
1034 . '</span>';
1035
1036 if ($this->totalItems > ($this->firstElementNumber + $this->iLimit)) {
1037 $lastElementNumber = $this->firstElementNumber + $this->iLimit;
1038 } else {
1039 $lastElementNumber = $this->totalItems;
1040 }
1041 $rangeIndicator = '<span class="pageIndicator">'
1042 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:rangeIndicator'), $this->firstElementNumber + 1, $lastElementNumber)
1043 . '</span>';
1044
1045 $content .= '<div id="typo3-dblist-pagination">'
1046 . $first . $previous
1047 . '<span class="bar">&nbsp;</span>'
1048 . $rangeIndicator . '<span class="bar">&nbsp;</span>'
1049 . $pageIndicator . '<span class="bar">&nbsp;</span>'
1050 . $next . $last . '<span class="bar">&nbsp;</span>'
1051 . $reload
1052 . '</div>';
1053 } // end of if pages > 1
1054
1055 $data = Array();
1056 $titleColumn = $this->fieldArray[0];
1057 $data[$titleColumn] = $content;
1058
1059 return ($this->addElement(1, '', $data));
1060 }
1061
1062
1063
1064
1065
1066
1067 /*********************************
1068 *
1069 * Rendering of various elements
1070 *
1071 *********************************/
1072
1073 /**
1074 * Creates the control panel for a single record in the listing.
1075 *
1076 * @param string The table
1077 * @param array The record for which to make the control panel.
1078 * @return string HTML table with the control panel (unless disabled)
1079 */
1080 function makeControl($table,$row) {
1081 global $TCA, $LANG, $SOBE, $TYPO3_CONF_VARS;
1082
1083 if ($this->dontShowClipControlPanels) return '';
1084
1085 // Initialize:
1086 t3lib_div::loadTCA($table);
1087 $cells=array();
1088
1089 // If the listed table is 'pages' we have to request the permission settings for each page:
1090 if ($table=='pages') {
1091 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$row['uid']));
1092 }
1093
1094 // This expresses the edit permissions for this particular element:
1095 $permsEdit = ($table=='pages' && ($localCalcPerms&2)) || ($table!='pages' && ($this->calcPerms&16));
1096
1097 // "Show" link (only pages and tt_content elements)
1098 if ($table=='pages' || $table=='tt_content') {
1099 $params='&edit['.$table.']['.$row['uid'].']=edit';
1100 $cells['view']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($table=='tt_content'?$this->id.'#'.$row['uid']:$row['uid'], $this->backPath)).'">'.
1101 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/zoom.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPage',1).'" alt="" />'.
1102 '</a>';
1103 } elseif(!$this->table) {
1104 $cells['view'] = $this->spaceIcon;
1105 }
1106
1107 // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
1108 if ($permsEdit) {
1109 $params='&edit['.$table.']['.$row['uid'].']=edit';
1110 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
1111 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2'.(!$TCA[$table]['ctrl']['readOnly']?'':'_d').'.gif','width="11" height="12"').' title="'.$LANG->getLL('edit',1).'" alt="" />'.
1112 '</a>';
1113 } elseif(!$this->table) {
1114 $cells['edit'] = $this->spaceIcon;
1115 }
1116
1117 // "Move" wizard link for pages/tt_content elements:
1118 if (($table=="tt_content" && $permsEdit) || ($table=='pages')) {
1119 $cells['move']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'move_el.php?table='.$table.'&uid='.$row['uid'].'\');').'">'.
1120 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/move_'.($table=='tt_content'?'record':'page').'.gif','width="11" height="12"').' title="'.$LANG->getLL('move_'.($table=='tt_content'?'record':'page'),1).'" alt="" />'.
1121 '</a>';
1122 } elseif(!$this->table) {
1123 $cells['move'] = $this->spaceIcon;
1124 }
1125
1126 // If the extended control panel is enabled OR if we are seeing a single table:
1127 if ($SOBE->MOD_SETTINGS['bigControlPanel'] || $this->table) {
1128
1129 // "Info": (All records)
1130 $cells['viewBig']='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$row['uid'].'\'); return false;').'">'.
1131 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/zoom2.gif','width="12" height="12"').' title="'.$LANG->getLL('showInfo',1).'" alt="" />'.
1132 '</a>';
1133
1134 // If the table is NOT a read-only table, then show these links:
1135 if (!$TCA[$table]['ctrl']['readOnly']) {
1136
1137 // "Revert" link (history/undo)
1138 $cells['history']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$row['uid']).'\',\'#latest\');').'">'.
1139 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/history2.gif','width="13" height="12"').' title="'.$LANG->getLL('history',1).'" alt="" />'.
1140 '</a>';
1141
1142 // Versioning:
1143 if (t3lib_extMgm::isLoaded('version')) {
1144 $vers = t3lib_BEfunc::selectVersionsOfRecord($table, $row['uid'], 'uid', $GLOBALS['BE_USER']->workspace, FALSE, $row);
1145 if (is_array($vers)) { // If table can be versionized.
1146 if (count($vers)>1) {
1147 $class = 'typo3-ctrl-versioning-multipleVersions';
1148 $lab = count($vers)-1;
1149 } else {
1150 $class = 'typo3-ctrl-versioning-oneVersion';
1151 $lab = 'V';
1152 }
1153
1154 $cells['version']='<a href="'.htmlspecialchars($this->backPath.t3lib_extMgm::extRelPath('version')).'cm1/index.php?table='.rawurlencode($table).'&uid='.rawurlencode($row['uid']).'" title="'.$LANG->getLL('displayVersions',1).'" class="typo3-ctrl-versioning ' . $class . '">'.
1155 $lab.
1156 '</a>';
1157 } elseif(!$this->table) {
1158 $cells['version'] = '<span class="typo3-ctrl-versioning typo3-ctrl-versioning-hidden">V</span>';
1159 }
1160 }
1161
1162 // "Edit Perms" link:
1163 if ($table=='pages' && $GLOBALS['BE_USER']->check('modules','web_perm')) {
1164 $cells['perms']='<a href="'.htmlspecialchars('mod/web/perm/index.php?id='.$row['uid'].'&return_id='.$row['uid'].'&edit=1').'">'.
1165 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/perm.gif','width="7" height="12"').' title="'.$LANG->getLL('permissions',1).'" alt="" />'.
1166 '</a>';
1167 } elseif(!$this->table && $GLOBALS['BE_USER']->check('modules','web_perm')) {
1168 $cells['perms'] = $this->spaceIcon;
1169 }
1170
1171 // "New record after" link (ONLY if the records in the table are sorted by a "sortby"-row or if default values can depend on previous record):
1172 if ($TCA[$table]['ctrl']['sortby'] || $TCA[$table]['ctrl']['useColumnsForDefaultValues']) {
1173 if (
1174 ($table!='pages' && ($this->calcPerms&16)) || // For NON-pages, must have permission to edit content on this parent page
1175 ($table=='pages' && ($this->calcPerms&8)) // For pages, must have permission to create new pages here.
1176 ) {
1177 if ($this->showNewRecLink($table)) {
1178 $params='&edit['.$table.']['.(-($row['_MOVE_PLH']?$row['_MOVE_PLH_uid']:$row['uid'])).']=new';
1179 $cells['new']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
1180 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new'.($table=='pages'?'Page':'Record'),1).'" alt="" />'.
1181 '</a>';
1182 }
1183 }
1184 } elseif(!$this->table) {
1185 $cells['new'] = $this->spaceIcon;
1186 }
1187
1188 // "Up/Down" links
1189 if ($permsEdit && $TCA[$table]['ctrl']['sortby'] && !$this->sortField && !$this->searchLevels) {
1190 if (isset($this->currentTable['prev'][$row['uid']])) { // Up
1191 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prev'][$row['uid']];
1192 $cells['moveUp']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1193 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_up.gif','width="11" height="10"').' title="'.$LANG->getLL('moveUp',1).'" alt="" />'.
1194 '</a>';
1195 } else {
1196 $cells['moveUp'] = $this->spaceIcon;
1197 }
1198 if ($this->currentTable['next'][$row['uid']]) { // Down
1199 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['next'][$row['uid']];
1200 $cells['moveDown']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1201 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_down.gif','width="11" height="10"').' title="'.$LANG->getLL('moveDown',1).'" alt="" />'.
1202 '</a>';
1203 } else {
1204 $cells['moveDown'] = $this->spaceIcon;
1205 }
1206 } elseif(!$this->table) {
1207 $cells['moveUp'] = $this->spaceIcon;
1208 $cells['moveDown'] = $this->spaceIcon;
1209 }
1210
1211 // "Hide/Unhide" links:
1212 $hiddenField = $TCA[$table]['ctrl']['enablecolumns']['disabled'];
1213 if ($permsEdit && $hiddenField && $TCA[$table]['columns'][$hiddenField] && (!$TCA[$table]['columns'][$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$table.':'.$hiddenField))) {
1214 if ($row[$hiddenField]) {
1215 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=0';
1216 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1217 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_unhide.gif','width="11" height="10"').' title="'.$LANG->getLL('unHide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1218 '</a>';
1219 } else {
1220 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=1';
1221 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1222 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_hide.gif','width="11" height="10"').' title="'.$LANG->getLL('hide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1223 '</a>';
1224 }
1225 } elseif(!$this->table) {
1226 $cells['hide'] = $this->spaceIcon;
1227 }
1228
1229 // "Delete" link:
1230 if (($table=='pages' && ($localCalcPerms&4)) || ($table!='pages' && ($this->calcPerms&16))) {
1231 $titleOrig = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
1232 $title = t3lib_div::slashJS(t3lib_div::fixed_lgd_cs($titleOrig, $this->fixedL), 1);
1233 $params = '&cmd['.$table.']['.$row['uid'].'][delete]=1';
1234
1235 $refCountMsg = t3lib_BEfunc::referenceCount($table, $row['uid'], ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.referencesToRecord'), count($this->references));
1236 $cells['delete']='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$LANG->JScharCode($LANG->getLL('deleteWarning').' "'. $title.'" '.$refCountMsg).')) {jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');} return false;').'">'.
1237 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$LANG->getLL('delete',1).'" alt="" />'.
1238 '</a>';
1239 } elseif(!$this->table) {
1240 $cells['delete'] = $this->spaceIcon;
1241 }
1242
1243 // "Levels" links: Moving pages into new levels...
1244 if ($permsEdit && $table=='pages' && !$this->searchLevels) {
1245
1246 // Up (Paste as the page right after the current parent page)
1247 if ($this->calcPerms&8) {
1248 $params='&cmd['.$table.']['.$row['uid'].'][move]='.-$this->id;
1249 $cells['moveLeft']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1250 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_left.gif','width="11" height="10"').' title="'.$LANG->getLL('prevLevel',1).'" alt="" />'.
1251 '</a>';
1252 }
1253 // Down (Paste as subpage to the page right above)
1254 if ($this->currentTable['prevUid'][$row['uid']]) {
1255 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$this->currentTable['prevUid'][$row['uid']]));
1256 if ($localCalcPerms&8) {
1257 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prevUid'][$row['uid']];
1258 $cells['moveRight']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1259 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_right.gif','width="11" height="10"').' title="'.$LANG->getLL('nextLevel',1).'" alt="" />'.
1260 '</a>';
1261 } else {
1262 $cells['moveRight'] = $this->spaceIcon;
1263 }
1264 } else {
1265 $cells['moveRight'] = $this->spaceIcon;
1266 }
1267 } elseif(!$this->table) {
1268 $cells['moveLeft'] = $this->spaceIcon;
1269 $cells['moveRight'] = $this->spaceIcon;
1270 }
1271 }
1272 }
1273
1274
1275 /**
1276 * @hook recStatInfoHooks: Allows to insert HTML before record icons on various places
1277 * @date 2007-09-22
1278 * @request Kasper Skaarhoj <kasper2007@typo3.com>
1279 */
1280 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) {
1281 $stat='';
1282 $_params = array($table,$row['uid']);
1283 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) {
1284 $stat.=t3lib_div::callUserFunction($_funcRef,$_params,$this);
1285 }
1286 $cells['stat'] = $stat;
1287 }
1288 /**
1289 * @hook makeControl: Allows to change control icons of records in list-module
1290 * @date 2007-11-20
1291 * @request Bernhard Kraft <krafbt@kraftb.at>
1292 * @usage This hook method gets passed the current $cells array as third parameter. This array contains values for the icons/actions generated for each record in Web>List. Each array entry is accessible by an index-key. The order of the icons is dependend on the order of those array entries.
1293 */
1294 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1295 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1296 $hookObject = &t3lib_div::getUserObj($classData);
1297 if(!($hookObject instanceof localRecordList_actionsHook)) {
1298 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567840);
1299 }
1300 $cells = $hookObject->makeControl($table, $row, $cells, $this);
1301 }
1302 }
1303
1304 // Compile items into a DIV-element:
1305 return '
1306 <!-- CONTROL PANEL: '.$table.':'.$row['uid'].' -->
1307 <div class="typo3-DBctrl">'.implode('',$cells).'</div>';
1308 }
1309
1310 /**
1311 * Creates the clipboard panel for a single record in the listing.
1312 *
1313 * @param string The table
1314 * @param array The record for which to make the clipboard panel.
1315 * @return string HTML table with the clipboard panel (unless disabled)
1316 */
1317 function makeClip($table,$row) {
1318 global $TCA, $LANG, $TYPO3_CONF_VARS;
1319
1320 // Return blank, if disabled:
1321 if ($this->dontShowClipControlPanels) return '';
1322 $cells=array();
1323
1324 $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon;
1325
1326 // Return blank, if disabled:
1327 // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel:
1328 if ($this->clipObj->current=='normal') { // For the "Normal" pad:
1329
1330 // Show copy/cut icons:
1331 $isSel = (string)$this->clipObj->isSelected($table,$row['uid']);
1332 $cells['copy']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'.
1333 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_copy'.($isSel=='copy'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.copy',1).'" alt="" />'.
1334 '</a>';
1335 $cells['cut']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'.
1336 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_cut'.($isSel=='cut'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.cut',1).'" alt="" />'.
1337 '</a>';
1338
1339 } else { // For the numeric clipboard pads (showing checkboxes where one can select elements on/off)
1340
1341 // Setting name of the element in ->CBnames array:
1342 $n=$table.'|'.$row['uid'];
1343 $this->CBnames[]=$n;
1344
1345 // Check if the current element is selected and if so, prepare to set the checkbox as selected:
1346 $checked = ($this->clipObj->isSelected($table,$row['uid'])?' checked="checked"':'');
1347
1348 // If the "duplicateField" value is set then select all elements which are duplicates...
1349 if ($this->duplicateField && isset($row[$this->duplicateField])) {
1350 $checked='';
1351 if (in_array($row[$this->duplicateField], $this->duplicateStack)) {
1352 $checked=' checked="checked"';
1353 }
1354 $this->duplicateStack[] = $row[$this->duplicateField];
1355 }
1356
1357 // Adding the checkbox to the panel:
1358 $cells['select']='<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />';
1359 }
1360
1361 // Now, looking for selected elements from the current table:
1362 $elFromTable = $this->clipObj->elFromTable($table);
1363 if (count($elFromTable) && $TCA[$table]['ctrl']['sortby']) { // IF elements are found and they can be individually ordered, then add a "paste after" icon:
1364 $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,-$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'after',$elFromTable)).'">'.
1365 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteAfter',1).'" alt="" />'.
1366 '</a>';
1367 }
1368
1369 // Now, looking for elements in general:
1370 $elFromTable = $this->clipObj->elFromTable('');
1371 if ($table=='pages' && count($elFromTable)) {
1372 $cells['pasteInto']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl('',$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'into',$elFromTable)).'">'.
1373 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteinto.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteInto',1).'" alt="" />'.
1374 '</a>';
1375 }
1376
1377 /*
1378 * @hook makeClip: Allows to change clip-icons of records in list-module
1379 * @date 2007-11-20
1380 * @request Bernhard Kraft <krafbt@kraftb.at>
1381 * @usage This hook method gets passed the current $cells array as third parameter. This array contains values for the clipboard icons generated for each record in Web>List. Each array entry is accessible by an index-key. The order of the icons is dependend on the order of those array entries.
1382 */
1383 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1384 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1385 $hookObject = &t3lib_div::getUserObj($classData);
1386 if(!($hookObject instanceof localRecordList_actionsHook)) {
1387 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567845);
1388 }
1389 $cells = $hookObject->makeClip($table, $row, $cells, $this);
1390 }
1391 }
1392
1393 // Compile items into a DIV-element:
1394 return ' <!-- CLIPBOARD PANEL: '.$table.':'.$row['uid'].' -->
1395 <div class="typo3-clipCtrl">'.implode('',$cells).'</div>';
1396 }
1397
1398 /**
1399 * Make reference count
1400 *
1401 * @param string Table name
1402 * @param integer UID of record
1403 * @return string HTML-table
1404 */
1405 function makeRef($table,$uid) {
1406
1407 // Compile information for title tag:
1408 $infoData=array();
1409 if (is_array($this->references)) {
1410 foreach ($this->references as $row) {
1411 $infoData[]=$row['tablename'].':'.$row['recuid'].':'.$row['field'];
1412 }
1413 }
1414
1415 return count($infoData) ? '<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$uid.'\'); return false;').'" title="'.htmlspecialchars(t3lib_div::fixed_lgd_cs(implode(' / ',$infoData),100)).'">'.count($infoData).'</a>' : '';
1416 }
1417
1418 /**
1419 * Creates the localization panel
1420 *
1421 * @param string The table
1422 * @param array The record for which to make the localization panel.
1423 * @return array Array with key 0/1 with content for column 1 and 2
1424 */
1425 function makeLocalizationPanel($table,$row) {
1426 global $TCA,$LANG;
1427
1428 $out = array(
1429 0 => '',
1430 1 => '',
1431 );
1432
1433 $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList);
1434 $this->translations = $translations['translations'];
1435
1436 // Language title and icon:
1437 $out[0] = $this->languageFlag($row[$TCA[$table]['ctrl']['languageField']]);
1438
1439 if (is_array($translations)) {
1440
1441 // Traverse page translations and add icon for each language that does NOT yet exist:
1442 $lNew = '';
1443 foreach($this->pageOverlays as $lUid_OnPage => $lsysRec) {
1444 if (!isset($translations['translations'][$lUid_OnPage]) && $GLOBALS['BE_USER']->checkLanguageAccess($lUid_OnPage)) {
1445 $href = $GLOBALS['TBE_TEMPLATE']->issueCommand(
1446 '&cmd['.$table.']['.$row['uid'].'][localize]='.$lUid_OnPage,
1447 $this->listURL().'&justLocalized='.rawurlencode($table.':'.$row['uid'].':'.$lUid_OnPage)
1448 );
1449
1450 $lC = ($this->languageIconTitles[$lUid_OnPage]['flagIcon'] ? '<img src="'.$this->languageIconTitles[$lUid_OnPage]['flagIcon'].'" class="absmiddle" alt="" />' : $this->languageIconTitles[$lUid_OnPage]['title']);
1451 $lC = '<a href="'.htmlspecialchars($href).'">'.$lC.'</a> ';
1452
1453 $lNew.=$lC;
1454 }
1455 }
1456
1457 if ($lNew) $out[1].= $lNew;
1458 } else {
1459 $out[0] = '&nbsp;&nbsp;&nbsp;&nbsp;'.$out[0];
1460 }
1461
1462
1463 return $out;
1464 }
1465
1466 /**
1467 * Create the selector box for selecting fields to display from a table:
1468 *
1469 * @param string Table name
1470 * @param boolean If true, form-fields will be wrapped around the table.
1471 * @return string HTML table with the selector box (name: displayFields['.$table.'][])
1472 */
1473 function fieldSelectBox($table,$formFields=1) {
1474 global $TCA, $LANG;
1475
1476 // Init:
1477 t3lib_div::loadTCA($table);
1478 $formElements=array('','');
1479 if ($formFields) {
1480 $formElements=array('<form action="'.htmlspecialchars($this->listURL()).'" method="post">','</form>');
1481 }
1482
1483 // Load already selected fields, if any:
1484 $setFields=is_array($this->setFields[$table]) ? $this->setFields[$table] : array();
1485
1486 // Request fields from table:
1487 $fields = $this->makeFieldList($table, false, true);
1488
1489 // Add pseudo "control" fields
1490 $fields[]='_PATH_';
1491 $fields[]='_REF_';
1492 $fields[]='_LOCALIZATION_';
1493 $fields[]='_CONTROL_';
1494 $fields[]='_CLIPBOARD_';
1495
1496 // Create an option for each field:
1497 $opt=array();
1498 $opt[] = '<option value=""></option>';
1499 foreach($fields as $fN) {
1500 $fL = is_array($TCA[$table]['columns'][$fN]) ? rtrim($LANG->sL($TCA[$table]['columns'][$fN]['label']),':') : '['.$fN.']'; // Field label
1501 $opt[] = '
1502 <option value="'.$fN.'"'.(in_array($fN,$setFields)?' selected="selected"':'').'>'.htmlspecialchars($fL).'</option>';
1503 }
1504
1505 // Compile the options into a multiple selector box:
1506 $lMenu = '
1507 <select size="'.t3lib_div::intInRange(count($fields)+1,3,20).'" multiple="multiple" name="displayFields['.$table.'][]">'.implode('',$opt).'
1508 </select>
1509 ';
1510
1511 // Table with the field selector::
1512 $content.= '
1513 '.$formElements[0].'
1514
1515 <!--
1516 Field selector for extended table view:
1517 -->
1518 <table border="0" cellpadding="0" cellspacing="0" class="bgColor4" id="typo3-dblist-fieldSelect">
1519 <tr>
1520 <td>'.$lMenu.'</td>
1521 <td><input type="submit" name="search" value="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.setFields',1).'" /></td>
1522 </tr>
1523 </table>
1524 '.$formElements[1];
1525 return $content;
1526 }
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538 /*********************************
1539 *
1540 * Helper functions
1541 *
1542 *********************************/
1543
1544 /**
1545 * Creates a link around $string. The link contains an onclick action which submits the script with some clipboard action.
1546 * Currently, this is used for setting elements / delete elements.
1547 *
1548 * @param string The HTML content to link (image/text)
1549 * @param string Table name
1550 * @param string Clipboard command (eg. "setCB" or "delete")
1551 * @param string Warning text, if any ("delete" uses this for confirmation)
1552 * @return string <a> tag wrapped link.
1553 */
1554 function linkClipboardHeaderIcon($string,$table,$cmd,$warning='') {
1555 $onClickEvent = 'document.dblistForm.cmd.value=\''.$cmd.'\';document.dblistForm.cmd_table.value=\''.$table.'\';document.dblistForm.submit();';
1556 if ($warning) $onClickEvent = 'if (confirm('.$GLOBALS['LANG']->JScharCode($warning).')){'.$onClickEvent.'}';
1557 return '<a href="#" onclick="'.htmlspecialchars($onClickEvent.'return false;').'">'.$string.'</a>';
1558 }
1559
1560 /**
1561 * Returns true if a numeric clipboard pad is selected/active
1562 *
1563 * @return boolean
1564 */
1565 function clipNumPane() {
1566 return in_Array('_CLIPBOARD_',$this->fieldArray) && $this->clipObj->current!='normal';
1567 }
1568
1569 /**
1570 * Creates a sort-by link on the input string ($code).
1571 * It will automatically detect if sorting should be ascending or descending depending on $this->sortRev.
1572 * Also some fields will not be possible to sort (including if single-table-view is disabled).
1573 *
1574 * @param string The string to link (text)
1575 * @param string The fieldname represented by the title ($code)
1576 * @param string Table name
1577 * @return string Linked $code variable
1578 */
1579 function addSortLink($code,$field,$table) {
1580
1581 // Certain circumstances just return string right away (no links):
1582 if ($field=='_CONTROL_' || $field=='_LOCALIZATION_' || $field=='_CLIPBOARD_' || $field=='_REF_' || $this->disableSingleTableView) return $code;
1583
1584 // If "_PATH_" (showing record path) is selected, force sorting by pid field (will at least group the records!)
1585 if ($field=='_PATH_') $field=pid;
1586
1587 // Create the sort link:
1588 $sortUrl = $this->listURL('',-1,'sortField,sortRev,table').'&table='.$table.'&sortField='.$field.'&sortRev='.($this->sortRev || ($this->sortField!=$field)?0:1);
1589 $sortArrow = ($this->sortField==$field?'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/red'.($this->sortRev?'up':'down').'.gif','width="7" height="4"').' alt="" />':'');
1590
1591 // Return linked field:
1592 return '<a href="'.htmlspecialchars($sortUrl).'">'.$code.
1593 $sortArrow.
1594 '</a>';
1595 }
1596
1597 /**
1598 * Returns the path for a certain pid
1599 * The result is cached internally for the session, thus you can call this function as much as you like without performance problems.
1600 *
1601 * @param integer The page id for which to get the path
1602 * @return string The path.
1603 */
1604 function recPath($pid) {
1605 if (!isset($this->recPath_cache[$pid])) {
1606 $this->recPath_cache[$pid] = t3lib_BEfunc::getRecordPath($pid,$this->perms_clause,20);
1607 }
1608 return $this->recPath_cache[$pid];
1609 }
1610
1611 /**
1612 * Returns true if a link for creating new records should be displayed for $table
1613 *
1614 * @param string Table name
1615 * @return boolean Returns true if a link for creating new records should be displayed for $table
1616 * @see SC_db_new::showNewRecLink
1617 */
1618 function showNewRecLink($table) {
1619 // No deny/allow tables are set:
1620 if (!count($this->allowedNewTables) && !count($this->deniedNewTables)) {
1621 return true;
1622 // If table is not denied (which takes precedence over allowed tables):
1623 } elseif (!in_array($table, $this->deniedNewTables) && (!count($this->allowedNewTables) || in_array($table, $this->allowedNewTables))) {
1624 return true;
1625 // If table is denied or allowed tables are set, but table is not part of:
1626 } else {
1627 return false;
1628 }
1629 }
1630
1631 /**
1632 * Creates the "&returnUrl" parameter for links - this is used when the script links to other scripts and passes its own URL with the link so other scripts can return to the listing again.
1633 * Uses REQUEST_URI as value.
1634 *
1635 * @return string
1636 */
1637 function makeReturnUrl() {
1638 return '&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
1639 }
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651 /************************************
1652 *
1653 * CSV related functions
1654 *
1655 ************************************/
1656
1657 /**
1658 * Initializes internal csvLines array with the header of field names
1659 *
1660 * @return void
1661 */
1662 function initCSV() {
1663
1664 // Reset:
1665 $this->csvLines=array();
1666
1667 // Getting header line with field names:
1668 $csvRow = array();
1669 foreach ($this->fieldArray as $fN) {
1670 if ($fN == '_CONTROL_' || $fN == '_CLIPBOARD_') {
1671 continue;
1672 }
1673 $csvRow[] = $fN;
1674 }
1675
1676 // Set the header + an empty row:
1677 $this->setCsvRow($csvRow);
1678 $this->csvLines[] = '';
1679 }
1680
1681
1682 /**
1683 * Adds the content of input array $row to the CSV list:
1684 *
1685 * @param array Record array, from which the values of fields found in $this->fieldArray will be listed in the CSV output.
1686 * @param string Table name
1687 * @return void
1688 */
1689 function addToCSV($row,$table) {
1690
1691 // Traversing fields, adding values from $row:
1692 $csvRow = array();
1693 foreach ($this->fieldArray as $fN) {
1694 switch ($fN) {
1695 case '_PATH':
1696 $csvRow[] = $this->recPath($row['pid']);
1697 break;
1698
1699 case '_REF_':
1700 $csvRow[] = $this->makeRef($table, $row['uid']);
1701 break;
1702
1703 // remove these columns from the CSV view
1704 case '_CONTROL_':
1705 case '_CLIPBOARD_':
1706 continue;
1707 break;
1708
1709 default:
1710 $csvRow[] = $row[$fN];
1711 }
1712 }
1713
1714 // Set the values in the CSV list
1715 $this->setCsvRow($csvRow);
1716 }
1717
1718
1719 /**
1720 * Adds input row of values to the internal csvLines array as a CSV formatted line
1721 *
1722 * @param array Array with values to be listed.
1723 * @return void
1724 */
1725 function setCsvRow($csvRow) {
1726 $this->csvLines[] = t3lib_div::csvValues($csvRow);
1727 }
1728
1729 /**
1730 * Compiles the internal csvLines array to a csv-string and outputs it to the browser.
1731 * This function exits!
1732 *
1733 * @param string Filename prefix:
1734 * @return void EXITS php execusion!
1735 */
1736 function outputCSV($prefix) {
1737
1738 // Setting filename:
1739 $filename=$prefix.'_'.date('dmy-Hi').'.csv';
1740
1741 // Creating output header:
1742 $mimeType = 'application/octet-stream';
1743 Header('Content-Type: '.$mimeType);
1744 Header('Content-Disposition: attachment; filename='.$filename);
1745
1746 // Printing the content of the CSV lines:
1747 echo implode(chr(13).chr(10),$this->csvLines);
1748
1749 // Exits:
1750 exit;
1751 }
1752 }
1753
1754
1755
1756 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']) {
1757 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']);
1758 }
1759
1760 ?>