Fixed bug #12273: List view don't show if there are more records than displayed
[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                                         $url = $this->backPath . t3lib_extMgm::extRelPath('impexp') . 'app/index.php?tx_impexp[action]=export';
249                                         $buttons['export'] = '<a href="' . htmlspecialchars($url . '&tx_impexp[list][]=' . rawurlencode($this->table . ':' . $this->id)) . '">' .                                                                       '<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                                 } else {
574                                                 // show that there are more records than shown
575                                         if ($this->totalItems > $this->itemsLimitPerTable) {
576                                                 $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems;
577                                                 $hasMore = ($this->totalItems > $this->itemsLimitSingleTable);
578                                                 $iOut .= '<tr><td colspan="' . count($this->fieldArray) . '" style="padding:5px;">
579                                                                 <a href="'.htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '">' .
580                                                                 '<img' . t3lib_iconWorks::skinImg($this->backPath,'gfx/pildown.gif', 'width="14" height="14"') .' alt="" />'.
581                                                                 ' <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a>
582                                                                 </td></tr>';
583                                                 }
584
585                                 }
586
587                                         // The header row for the table is now created:
588                                 $out .= $this->renderListHeader($table,$currentIdList);
589                         }
590
591                                 // The list of records is added after the header:
592                         $out .= $iOut;
593                         unset($iOut);
594
595                                 // ... and it is all wrapped in a table:
596                         $out='
597
598
599
600                         <!--
601                                 DB listing of elements: "'.htmlspecialchars($table).'"
602                         -->
603                                 <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist'.($listOnlyInSingleTableMode?' typo3-dblist-overview':'').'">
604                                         '.$out.'
605                                 </table>';
606
607                                 // Output csv if...
608                         if ($this->csvOutput)   $this->outputCSV($table);       // This ends the page with exit.
609                 }
610
611                         // Return content:
612                 return $out;
613         }
614
615         /**
616          * Rendering a single row for the list
617          *
618          * @param       string          Table name
619          * @param       array           Current record
620          * @param       integer         Counter, counting for each time an element is rendered (used for alternating colors)
621          * @param       string          Table field (column) where header value is found
622          * @param       string          Table field (column) where (possible) thumbnails can be found
623          * @param       integer         Indent from left.
624          * @return      string          Table row for the element
625          * @access private
626          * @see getTable()
627          */
628         function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0)  {
629                 $iOut = '';
630
631                 if (strlen($this->searchString))        {       // If in search mode, make sure the preview will show the correct page
632                         $id_orig = $this->id;
633                         $this->id = $row['pid'];
634                 }
635
636                 if (is_array($row))     {
637
638                         $this->setReferences($table, $row['uid']);
639                                 // add special classes for first and last row
640                         $rowSpecial = '';
641                         if ($cc == 1 && $indent == 0) {
642                                 $rowSpecial .= ' firstcol';
643                         }
644                         if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
645                                 $rowSpecial .= ' lastcol';
646                         }
647
648                                 // Background color, if any:
649                         if ($this->alternateBgColors) {
650                                 $row_bgColor = ($cc%2) ? ' class="db_list_normal'.$rowSpecial.'"' : ' class="db_list_alt'.$rowSpecial.'"';
651                         } else {
652                                 $row_bgColor = ' class="db_list_normal'.$rowSpecial.'"';
653                         }
654                                 // Overriding with versions background color if any:
655                         $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor;
656
657                                 // Incr. counter.
658                         $this->counter++;
659
660                                 // The icon with link
661                         $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table);
662                         $iconImg = t3lib_iconWorks::getIconImage($table,$row,$this->backPath,'title="'.htmlspecialchars($alttext).'"'.($indent ? ' style="margin-left: '.$indent.'px;"' : ''));
663                         $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg;
664
665                                 // Preparing and getting the data-array
666                         $theData = Array();
667                         foreach($this->fieldArray as $fCol)     {
668                                 if ($fCol==$titleCol)   {
669                                         $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
670                                                 // If the record is edit-locked by another user, we will show a little warning sign:
671                                         if (($lockInfo = t3lib_BEfunc::isRecordLocked($table, $row['uid']))) {
672                                                 $warning = '<a href="#" onclick="' . htmlspecialchars('alert(' . $GLOBALS['LANG']->JScharCode($lockInfo['msg']) . '); return false;') . '">' .
673                                                         '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/recordlock_warning3.gif', 'width="17" height="12"') . ' title="' . htmlspecialchars($lockInfo['msg']) . '" alt="" />' .
674                                                         '</a>';
675                                         }
676                                         $theData[$fCol] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row);
677
678                                         $localizationMarkerClass = '';
679                                         if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField'])
680                                         && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0) {
681                                                         // it's a translated record
682                                                 $localizationMarkerClass = ' localization';
683                                         }
684                                 } elseif ($fCol == 'pid') {
685                                         $theData[$fCol]=$row[$fCol];
686                                 } elseif ($fCol == '_PATH_') {
687                                         $theData[$fCol]=$this->recPath($row['pid']);
688                                 } elseif ($fCol == '_REF_') {
689                                         $theData[$fCol]=$this->makeRef($table,$row['uid']);
690                                 } elseif ($fCol == '_CONTROL_') {
691                                         $theData[$fCol]=$this->makeControl($table,$row);
692                                 } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') {
693                                         $theData[$fCol] = '&nbsp;';
694                                 } elseif ($fCol == '_CLIPBOARD_') {
695                                         $theData[$fCol]=$this->makeClip($table,$row);
696                                 } elseif ($fCol == '_LOCALIZATION_') {
697                                         list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row);
698                                         $theData[$fCol] = $lC1;
699                                         $theData[$fCol.'b'] = $lC2;
700                                 } elseif ($fCol == '_LOCALIZATION_b') {
701                                         // Do nothing, has been done above.
702                                 } else {
703                                         $tmpProc = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']);
704                                         $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
705                                         $row[$fCol] = $tmpProc;
706                                 }
707                         }
708
709                         if (strlen($this->searchString))        {       // Reset the ID if it was overwritten
710                                 $this->id = $id_orig;
711                         }
712
713                                 // Add row to CSV list:
714                         if ($this->csvOutput) {
715                                 $this->addToCSV($row,$table);
716                         }
717
718                         // Add classes to table cells
719                         $this->addElement_tdCssClass[$titleCol]         = 'col-title' . $localizationMarkerClass;
720                         if (!$this->dontShowClipControlPanels) {
721                                 $this->addElement_tdCssClass['_CONTROL_']       = 'col-control';
722                                 $this->addElement_tdCssClass['_AFTERCONTROL_']  = 'col-control-space';
723                                 $this->addElement_tdCssClass['_CLIPBOARD_']     = 'col-clipboard';
724                         }
725                         $this->addElement_tdCssClass['_PATH_']          = 'col-path';
726                         $this->addElement_tdCssClass['_LOCALIZATION_']  = 'col-localizationa';
727                         $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb';
728
729
730                                 // Create element in table cells:
731                         $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor);
732
733                                 // Render thumbsnails if a thumbnail column exists and there is content in it:
734                         if ($this->thumbs && trim($row[$thumbsCol]))    {
735                                 $iOut.=$this->addelement(4,'', Array($titleCol=>$this->thumbCode($row,$table,$thumbsCol)),$row_bgColor);
736                         }
737
738                                 // Finally, return table row element:
739                         return $iOut;
740                 }
741         }
742
743         /**
744          * Write sys_refindex entries for current record to $this->references
745          *
746          * @param       string          Table name
747          * @param       integer         Uid of current record
748          * @return      void
749          */
750         function setReferences($table, $uid) {
751                 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
752                         '*',
753                         'sys_refindex',
754                         'ref_table='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_refindex').
755                                 ' AND ref_uid='.intval($uid).
756                                 ' AND deleted=0'
757                 );
758                 $this->references = $rows;
759         }
760
761         /**
762          * Rendering the header row for a table
763          *
764          * @param       string          Table name
765          * @param       array           Array of the currently displayed uids of the table
766          * @return      string          Header table row
767          * @access private
768          * @see getTable()
769          */
770         function renderListHeader($table, $currentIdList)       {
771                 global $TCA, $LANG, $TYPO3_CONF_VARS;
772
773                         // Init:
774                 $theData = Array();
775
776                         // Traverse the fields:
777                 foreach($this->fieldArray as $fCol)     {
778
779                                 // Calculate users permissions to edit records in the table:
780                         $permsEdit = $this->calcPerms & ($table=='pages'?2:16);
781
782                         switch((string)$fCol)   {
783                                 case '_PATH_':                  // Path
784                                         $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._PATH_',1).']</i>';
785                                 break;
786                                 case '_REF_':                   // References
787                                         $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_mod_file_list.xml:c__REF_',1).']</i>';
788                                 break;
789                                 case '_LOCALIZATION_':                  // Path
790                                         $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._LOCALIZATION_',1).']</i>';
791                                 break;
792                                 case '_LOCALIZATION_b':                 // Path
793                                         $theData[$fCol] = $LANG->getLL('Localize',1);
794                                 break;
795                                 case '_CLIPBOARD_':             // Clipboard:
796                                         $cells=array();
797
798                                                 // If there are elements on the clipboard for this table, then display the "paste into" icon:
799                                         $elFromTable = $this->clipObj->elFromTable($table);
800                                         if (count($elFromTable))        {
801                                                 $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,$this->id)).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg('pages',$this->pageRow,'into',$elFromTable)).'">'.
802                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_paste',1).'" alt="" />'.
803                                                                 '</a>';
804                                         }
805
806                                                 // If the numeric clipboard pads are enabled, display the control icons for that:
807                                         if ($this->clipObj->current!='normal')  {
808
809                                                         // The "select" link:
810                                                 $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');
811
812                                                         // The "edit marked" link:
813                                                 $editIdList = implode(',',$currentIdList);
814                                                 $editIdList = "'+editList('".$table."','".$editIdList."')+'";
815                                                 $params='&edit['.$table.']['.$editIdList.']=edit&disHelp=1';
816                                                 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
817                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('clip_editMarked',1).'" alt="" />'.
818                                                                 '</a>';
819
820                                                         // The "Delete marked" link:
821                                                 $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'])));
822
823                                                         // The "Select all" link:
824                                                 $cells['markAll']='<a href="#" onclick="'.htmlspecialchars('checkOffCB(\''.implode(',',$this->CBnames).'\'); return false;').'">'.
825                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_select.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_markRecords',1).'" alt="" />'.
826                                                                 '</a>';
827                                         } else {
828                                                 $cells['empty']='';
829                                         }
830                                         /**
831                                          * @hook                        renderListHeaderActions: Allows to change the clipboard icons of the Web>List table headers
832                                          * @date                        2007-11-20
833                                          * @request             Bernhard Kraft  <krafbt@kraftb.at>
834                                          * @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.
835                                          */
836                                         if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions']))        {
837                                                 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData)       {
838                                                         $hookObject = t3lib_div::getUserObj($classData);
839                                                         if(!($hookObject instanceof localRecordList_actionsHook))       {
840                                                                 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567850);
841                                                         }
842                                                         $cells = $hookObject->renderListHeaderActions($table, $currentIdList, $cells, $this);
843                                                 }
844                                         }
845                                         $theData[$fCol]=implode('',$cells);
846                                 break;
847                                 case '_CONTROL_':               // Control panel:
848                                         if (!$TCA[$table]['ctrl']['readOnly'])  {
849
850                                                         // If new records can be created on this page, add links:
851                                                 if ($this->calcPerms&($table=='pages'?8:16) && $this->showNewRecLink($table))   {
852                                                         if ($table=="tt_content" && $this->newWizards)  {
853                                                                         //  If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
854                                                                 $tmpTSc = t3lib_BEfunc::getModTSconfig($this->pageinfo['uid'],'mod.web_list');
855                                                                 $tmpTSc = $tmpTSc ['properties']['newContentWiz.']['overrideWithExtension'];
856                                                                 $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';
857
858                                                                 $icon = '<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$newContentWizScriptPath.'?id='.$this->id.'\');').'">'.
859                                                                                                 '<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="" />'.
860                                                                                                 '</a>';
861                                                         } elseif ($table=='pages' && $this->newWizards) {
862                                                                 $icon = '<a href="'.htmlspecialchars($this->backPath.'db_new.php?id='.$this->id.'&pagesOnly=1&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
863                                                                                                 '<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="" />'.
864                                                                                                 '</a>';
865
866                                                         } else {
867                                                                 $params = '&edit['.$table.']['.$this->id.']=new';
868                                                                 if ($table == 'pages_language_overlay') {
869                                                                         $params .= '&overrideVals[pages_language_overlay][doktype]=' . (int) $this->pageRow['doktype'];
870                                                                 }
871                                                                 $icon   = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
872                                                                                                 '<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="" />'.
873                                                                                                 '</a>';
874                                                         }
875                                                 }
876
877                                                         // If the table can be edited, add link for editing ALL SHOWN fields for all listed records:
878                                                 if ($permsEdit && $this->table && is_array($currentIdList))     {
879                                                         $editIdList = implode(',',$currentIdList);
880                                                         if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
881                                                         $params = '&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.implode(',',$this->fieldArray).'&disHelp=1';
882                                                         $icon  .= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
883                                                                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('editShownColumns',1).'" alt="" />'.
884                                                                                         '</a>';
885                                                 }
886                                                         // add an empty entry, so column count fits again after moving this into $icon
887                                                 $theData[$fCol] = '&nbsp;';
888                                         }
889                                 break;
890                                 case '_AFTERCONTROL_':  // space column
891                                 case '_AFTERREF_':      // space column
892                                         $theData[$fCol] = '&nbsp;';
893                                 break;
894                                 default:                        // Regular fields header:
895                                         $theData[$fCol]='';
896                                         if ($this->table && is_array($currentIdList))   {
897
898                                                         // If the numeric clipboard pads are selected, show duplicate sorting link:
899                                                 if ($this->clipNumPane()) {
900                                                         $theData[$fCol].='<a href="'.htmlspecialchars($this->listURL('',-1).'&duplicateField='.$fCol).'">'.
901                                                                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/select_duplicates.gif','width="11" height="11"').' title="'.$LANG->getLL('clip_duplicates',1).'" alt="" />'.
902                                                                                         '</a>';
903                                                 }
904
905                                                         // If the table can be edited, add link for editing THIS field for all listed records:
906                                                 if (!$TCA[$table]['ctrl']['readOnly'] && $permsEdit && $TCA[$table]['columns'][$fCol])  {
907                                                         $editIdList = implode(',',$currentIdList);
908                                                         if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
909                                                         $params='&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.$fCol.'&disHelp=1';
910                                                         $iTitle = sprintf($LANG->getLL('editThisColumn'),rtrim(trim($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol))),':'));
911                                                         $theData[$fCol].='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
912                                                                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.htmlspecialchars($iTitle).'" alt="" />'.
913                                                                                         '</a>';
914                                                 }
915                                         }
916                                         $theData[$fCol].=$this->addSortLink($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol,'<i>[|]</i>')),$fCol,$table);
917                                 break;
918                         }
919
920                 }
921
922                 /**
923                  * @hook                        renderListHeader: Allows to change the contents of columns/cells of the Web>List table headers
924                  * @date                        2007-11-20
925                  * @request             Bernhard Kraft  <krafbt@kraftb.at>
926                  * @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.
927                  */
928                 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions']))        {
929                         foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData)       {
930                                 $hookObject = t3lib_div::getUserObj($classData);
931                                 if(!($hookObject instanceof localRecordList_actionsHook))       {
932                                         throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567855);
933                                 }
934                                 $theData = $hookObject->renderListHeader($table, $currentIdList, $theData, $this);
935                         }
936                 }
937
938                         // Create and return header table row:
939                 return $this->addelement(1, $icon, $theData, ' class="c-headLine"', '');
940         }
941
942         /**
943          * Creates a page browser for tables with many records
944          *
945          * @return      string  Navigation HTML
946          *
947          * @author      Dmitry Pikhno <dpi@goldenplanet.com>
948          * @author      Christian Kuhn <lolli@schwarzbu.ch>
949          */
950         protected function renderListNavigation() {
951                 $totalPages = ceil($this->totalItems / $this->iLimit);
952
953                 $content = '';
954
955                         // Show page selector if not all records fit into one page
956                 if ($totalPages > 1) {
957                         $first = $previous = $next = $last = $reload = '';
958                         $listURL = $this->listURL('', $this->table);
959
960                                 // 1 = first page
961                         $currentPage = floor(($this->firstElementNumber + 1) / $this->iLimit) + 1;
962
963                                 // Compile first, previous, next, last and refresh buttons
964                         if ($currentPage > 1) {
965                                 $labelFirst = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:first');
966
967                                 $first = '<a href="' . $listURL . '&pointer=0">
968                                         <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_first.gif')
969                                         . 'alt="' . $labelFirst . '" title="' . $labelFirst . '" />
970                                 </a>';
971                         } else {
972                                 $first = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_first_disabled.gif') . 'alt="" title="" />';
973                         }
974
975                         if (($currentPage - 1) > 0) {
976                                 $labelPrevious = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:previous');
977
978                                 $previous = '<a href="' . $listURL . '&pointer=' . (($currentPage - 2) * $this->iLimit) . '">
979                                         <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_previous.gif')
980                                         . 'alt="' . $labelPrevious . '" title="' . $labelPrevious . '" />
981                                         </a>';
982                         } else {
983                                 $previous = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_previous_disabled.gif') . 'alt="" title="" />';
984                         }
985
986                         if (($currentPage + 1) <= $totalPages) {
987                                 $labelNext = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:next');
988
989                                 $next = '<a href="' . $listURL . '&pointer=' . (($currentPage) * $this->iLimit) . '">
990                                         <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_next.gif')
991                                         . 'alt="' . $labelNext . '" title="' . $labelNext . '" />
992                                         </a>';
993                         } else {
994                                 $next = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_next_disabled.gif') . 'alt="" title="" />';
995                         }
996
997                         if ($currentPage != $totalPages) {
998                                 $labelLast = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:last');
999
1000                                 $last = '<a href="' . $listURL . '&pointer=' . (($totalPages - 1) * $this->iLimit) . '">
1001                                         <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_last.gif')
1002                                         . 'alt="' . $labelLast . '" title="' . $labelLast . '" />
1003                                         </a>';
1004                         } else {
1005                                 $last = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_last_disabled.gif') . 'alt="" title="" />';
1006                         }
1007
1008                         $reload = '<a href="#" onclick="document.dblistForm.action=\''
1009                                 . $listURL . '&pointer=\'+calculatePointer(); document.dblistForm.submit(); return true;">
1010                                 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/refresh_n.gif')
1011                                 . 'alt="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:reload')
1012                                 . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:reload')
1013                                 . '" /></a>';
1014
1015                         // Add js to traverse a page select input to a pointer value
1016                         $content = '
1017 <script type="text/JavaScript">
1018 /*<![CDATA[*/
1019
1020         function calculatePointer(){
1021                 page = document.getElementById(\'jumpPage\').value;
1022
1023                 if (page > ' . $totalPages . ') {
1024                         page = ' . $totalPages . ';
1025                 }
1026
1027                 if (page < 1) {
1028                         page = 1;
1029                 }
1030
1031                 pointer = (page - 1) * ' . $this->iLimit . ';
1032
1033                 return pointer;
1034         }
1035
1036 /*]]>*/
1037 </script>
1038 ';
1039
1040                         $pageNumberInput = '<span>
1041                                 <input type="text" value="' . $currentPage
1042                                 . '" size="3" id="jumpPage" name="jumpPage" onkeyup="if (event.keyCode == Event.KEY_RETURN) { document.dblistForm.action=\'' . $listURL . '&pointer=\'+calculatePointer(); document.dblistForm.submit(); } return true;" />
1043                                 </span>';
1044                         $pageIndicator = '<span class="pageIndicator">'
1045                                 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:pageIndicator'), $pageNumberInput, $totalPages)
1046                                 . '</span>';
1047
1048                         if ($this->totalItems > ($this->firstElementNumber + $this->iLimit)) {
1049                                 $lastElementNumber = $this->firstElementNumber + $this->iLimit;
1050                         } else {
1051                                 $lastElementNumber = $this->totalItems;
1052                         }
1053                         $rangeIndicator = '<span class="pageIndicator">'
1054                                 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:rangeIndicator'), $this->firstElementNumber + 1, $lastElementNumber)
1055                                 . '</span>';
1056
1057                         $content .= '<div id="typo3-dblist-pagination">'
1058                                 . $first . $previous
1059                                 . '<span class="bar">&nbsp;</span>'
1060                                 . $rangeIndicator . '<span class="bar">&nbsp;</span>'
1061                                 . $pageIndicator . '<span class="bar">&nbsp;</span>'
1062                                 . $next . $last . '<span class="bar">&nbsp;</span>'
1063                                 . $reload
1064                                 . '</div>';
1065                 } // end of if pages > 1
1066
1067                 $data = Array();
1068                 $titleColumn = $this->fieldArray[0];
1069                 $data[$titleColumn] = $content;
1070
1071                 return ($this->addElement(1, '', $data));
1072         }
1073
1074
1075
1076
1077
1078
1079         /*********************************
1080          *
1081          * Rendering of various elements
1082          *
1083          *********************************/
1084
1085         /**
1086          * Creates the control panel for a single record in the listing.
1087          *
1088          * @param       string          The table
1089          * @param       array           The record for which to make the control panel.
1090          * @return      string          HTML table with the control panel (unless disabled)
1091          */
1092         function makeControl($table,$row)       {
1093                 global $TCA, $LANG, $SOBE, $TYPO3_CONF_VARS;
1094
1095                 if ($this->dontShowClipControlPanels)   return '';
1096
1097                         // Initialize:
1098                 t3lib_div::loadTCA($table);
1099                 $cells=array();
1100
1101                         // If the listed table is 'pages' we have to request the permission settings for each page:
1102                 if ($table=='pages')    {
1103                         $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$row['uid']));
1104                 }
1105
1106                         // This expresses the edit permissions for this particular element:
1107                 $permsEdit = ($table=='pages' && ($localCalcPerms&2)) || ($table!='pages' && ($this->calcPerms&16));
1108
1109                         // "Show" link (only pages and tt_content elements)
1110                 if ($table=='pages' || $table=='tt_content')    {
1111                         $params='&edit['.$table.']['.$row['uid'].']=edit';
1112                         $cells['view']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($table=='tt_content'?$this->id.'#'.$row['uid']:$row['uid'], $this->backPath)).'">'.
1113                                         '<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="" />'.
1114                                         '</a>';
1115                 } elseif(!$this->table) {
1116                         $cells['view'] = $this->spaceIcon;
1117                 }
1118
1119                         // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
1120                 if ($permsEdit) {
1121                         $params='&edit['.$table.']['.$row['uid'].']=edit';
1122                         $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
1123                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2'.(!$TCA[$table]['ctrl']['readOnly']?'':'_d').'.gif','width="11" height="12"').' title="'.$LANG->getLL('edit',1).'" alt="" />'.
1124                                         '</a>';
1125                 } elseif(!$this->table) {
1126                         $cells['edit'] = $this->spaceIcon;
1127                 }
1128
1129                         // "Move" wizard link for pages/tt_content elements:
1130                 if (($table=="tt_content" && $permsEdit) || ($table=='pages'))  {
1131                         $cells['move']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'move_el.php?table='.$table.'&uid='.$row['uid'].'\');').'">'.
1132                                         '<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="" />'.
1133                                         '</a>';
1134                 } elseif(!$this->table) {
1135                         $cells['move'] = $this->spaceIcon;
1136                 }
1137
1138                         // If the extended control panel is enabled OR if we are seeing a single table:
1139                 if ($SOBE->MOD_SETTINGS['bigControlPanel'] || $this->table)     {
1140
1141                                 // "Info": (All records)
1142                         $cells['viewBig']='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$row['uid'].'\'); return false;').'">'.
1143                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/zoom2.gif','width="12" height="12"').' title="'.$LANG->getLL('showInfo',1).'" alt="" />'.
1144                                         '</a>';
1145
1146                                 // If the table is NOT a read-only table, then show these links:
1147                         if (!$TCA[$table]['ctrl']['readOnly'])  {
1148
1149                                         // "Revert" link (history/undo)
1150                                 $cells['history']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$row['uid']).'\',\'#latest\');').'">'.
1151                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/history2.gif','width="13" height="12"').' title="'.$LANG->getLL('history',1).'" alt="" />'.
1152                                                 '</a>';
1153
1154                                         // Versioning:
1155                                 if (t3lib_extMgm::isLoaded('version'))  {
1156                                         $vers = t3lib_BEfunc::selectVersionsOfRecord($table, $row['uid'], 'uid', $GLOBALS['BE_USER']->workspace, FALSE, $row);
1157                                         if (is_array($vers))    {       // If table can be versionized.
1158                                                 if (count($vers)>1)     {
1159                                                         $class = 'typo3-ctrl-versioning-multipleVersions';
1160                                                         $lab = count($vers)-1;
1161                                                 } else {
1162                                                         $class = 'typo3-ctrl-versioning-oneVersion';
1163                                                         $lab = 'V';
1164                                                 }
1165
1166                                                 $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 . '">'.
1167                                                                 $lab.
1168                                                                 '</a>';
1169                                         } elseif(!$this->table) {
1170                                                 $cells['version'] = '<span class="typo3-ctrl-versioning typo3-ctrl-versioning-hidden">V</span>';
1171                                         }
1172                                 }
1173
1174                                         // "Edit Perms" link:
1175                                 if ($table=='pages' && $GLOBALS['BE_USER']->check('modules','web_perm'))        {
1176                                         $cells['perms']='<a href="'.htmlspecialchars('mod/web/perm/index.php?id='.$row['uid'].'&return_id='.$row['uid'].'&edit=1').'">'.
1177                                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/perm.gif','width="7" height="12"').' title="'.$LANG->getLL('permissions',1).'" alt="" />'.
1178                                                         '</a>';
1179                                 } elseif(!$this->table && $GLOBALS['BE_USER']->check('modules','web_perm')) {
1180                                         $cells['perms'] = $this->spaceIcon;
1181                                 }
1182
1183                                         // "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):
1184                                 if ($TCA[$table]['ctrl']['sortby'] || $TCA[$table]['ctrl']['useColumnsForDefaultValues'])       {
1185                                         if (
1186                                                 ($table!='pages' && ($this->calcPerms&16)) ||   // For NON-pages, must have permission to edit content on this parent page
1187                                                 ($table=='pages' && ($this->calcPerms&8))               // For pages, must have permission to create new pages here.
1188                                                 )       {
1189                                                 if ($this->showNewRecLink($table))      {
1190                                                         $params='&edit['.$table.']['.(-($row['_MOVE_PLH']?$row['_MOVE_PLH_uid']:$row['uid'])).']=new';
1191                                                         $cells['new']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
1192                                                                         '<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="" />'.
1193                                                                         '</a>';
1194                                                 }
1195                                         }
1196                                 } elseif(!$this->table) {
1197                                         $cells['new'] = $this->spaceIcon;
1198                                 }
1199
1200                                         // "Up/Down" links
1201                                 if ($permsEdit && $TCA[$table]['ctrl']['sortby']  && !$this->sortField && !$this->searchLevels) {
1202                                         if (isset($this->currentTable['prev'][$row['uid']]))    {       // Up
1203                                                 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prev'][$row['uid']];
1204                                                 $cells['moveUp']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1205                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_up.gif','width="11" height="10"').' title="'.$LANG->getLL('moveUp',1).'" alt="" />'.
1206                                                                 '</a>';
1207                                         } else {
1208                                                 $cells['moveUp'] = $this->spaceIcon;
1209                                         }
1210                                         if ($this->currentTable['next'][$row['uid']])   {       // Down
1211                                                 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['next'][$row['uid']];
1212                                                 $cells['moveDown']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1213                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_down.gif','width="11" height="10"').' title="'.$LANG->getLL('moveDown',1).'" alt="" />'.
1214                                                                 '</a>';
1215                                         } else {
1216                                                 $cells['moveDown'] = $this->spaceIcon;
1217                                         }
1218                                 } elseif(!$this->table) {
1219                                         $cells['moveUp']  = $this->spaceIcon;
1220                                         $cells['moveDown'] = $this->spaceIcon;
1221                                 }
1222
1223                                         // "Hide/Unhide" links:
1224                                 $hiddenField = $TCA[$table]['ctrl']['enablecolumns']['disabled'];
1225                                 if ($permsEdit && $hiddenField && $TCA[$table]['columns'][$hiddenField] && (!$TCA[$table]['columns'][$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$table.':'.$hiddenField)))     {
1226                                         if ($row[$hiddenField]) {
1227                                                 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=0';
1228                                                 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1229                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_unhide.gif','width="11" height="10"').' title="'.$LANG->getLL('unHide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1230                                                                 '</a>';
1231                                         } else {
1232                                                 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=1';
1233                                                 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1234                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_hide.gif','width="11" height="10"').' title="'.$LANG->getLL('hide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1235                                                                 '</a>';
1236                                         }
1237                                 } elseif(!$this->table) {
1238                                         $cells['hide'] = $this->spaceIcon;
1239                                 }
1240
1241                                         // "Delete" link:
1242                                 if (($table=='pages' && ($localCalcPerms&4)) || ($table!='pages' && ($this->calcPerms&16))) {
1243                                         $titleOrig = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
1244                                         $title = t3lib_div::slashJS(t3lib_div::fixed_lgd_cs($titleOrig, $this->fixedL), 1);
1245                                         $params = '&cmd['.$table.']['.$row['uid'].'][delete]=1';
1246
1247                                         $refCountMsg = t3lib_BEfunc::referenceCount($table, $row['uid'], ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.referencesToRecord'), count($this->references));
1248                                         $cells['delete']='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$LANG->JScharCode($LANG->getLL('deleteWarning').' "'. $title.'" '.$refCountMsg).')) {jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');} return false;').'">'.
1249                                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$LANG->getLL('delete',1).'" alt="" />'.
1250                                                         '</a>';
1251                                 } elseif(!$this->table) {
1252                                         $cells['delete'] = $this->spaceIcon;
1253                                 }
1254
1255                                         // "Levels" links: Moving pages into new levels...
1256                                 if ($permsEdit && $table=='pages' && !$this->searchLevels)      {
1257
1258                                                 // Up (Paste as the page right after the current parent page)
1259                                         if ($this->calcPerms&8) {
1260                                                 $params='&cmd['.$table.']['.$row['uid'].'][move]='.-$this->id;
1261                                                 $cells['moveLeft']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1262                                                                 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_left.gif','width="11" height="10"').' title="'.$LANG->getLL('prevLevel',1).'" alt="" />'.
1263                                                                 '</a>';
1264                                         }
1265                                                 // Down (Paste as subpage to the page right above)
1266                                         if ($this->currentTable['prevUid'][$row['uid']])        {
1267                                                 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$this->currentTable['prevUid'][$row['uid']]));
1268                                                 if ($localCalcPerms&8)  {
1269                                                         $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prevUid'][$row['uid']];
1270                                                         $cells['moveRight']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1271                                                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_right.gif','width="11" height="10"').' title="'.$LANG->getLL('nextLevel',1).'" alt="" />'.
1272                                                                         '</a>';
1273                                                 } else {
1274                                                         $cells['moveRight'] = $this->spaceIcon;
1275                                                 }
1276                                         } else {
1277                                                 $cells['moveRight'] = $this->spaceIcon;
1278                                         }
1279                                 } elseif(!$this->table) {
1280                                         $cells['moveLeft'] = $this->spaceIcon;
1281                                         $cells['moveRight'] = $this->spaceIcon;
1282                                 }
1283                         }
1284                 }
1285
1286
1287                 /**
1288                  * @hook                        recStatInfoHooks: Allows to insert HTML before record icons on various places
1289                  * @date                        2007-09-22
1290                  * @request             Kasper Skaarhoj  <kasper2007@typo3.com>
1291                  */
1292                 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks']))     {
1293                         $stat='';
1294                         $_params = array($table,$row['uid']);
1295                         foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef)     {
1296                                 $stat.=t3lib_div::callUserFunction($_funcRef,$_params,$this);
1297                         }
1298                         $cells['stat'] = $stat;
1299                 }
1300                 /**
1301                  * @hook                        makeControl: Allows to change control icons of records in list-module
1302                  * @date                        2007-11-20
1303                  * @request             Bernhard Kraft  <krafbt@kraftb.at>
1304                  * @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.
1305                  */
1306                 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1307                         foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1308                                 $hookObject = t3lib_div::getUserObj($classData);
1309                                 if(!($hookObject instanceof localRecordList_actionsHook))       {
1310                                         throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567840);
1311                                 }
1312                                 $cells = $hookObject->makeControl($table, $row, $cells, $this);
1313                         }
1314                 }
1315
1316                         // Compile items into a DIV-element:
1317                 return '
1318                                                                                         <!-- CONTROL PANEL: '.$table.':'.$row['uid'].' -->
1319                                                                                         <div class="typo3-DBctrl">'.implode('',$cells).'</div>';
1320         }
1321
1322         /**
1323          * Creates the clipboard panel for a single record in the listing.
1324          *
1325          * @param       string          The table
1326          * @param       array           The record for which to make the clipboard panel.
1327          * @return      string          HTML table with the clipboard panel (unless disabled)
1328          */
1329         function makeClip($table,$row)  {
1330                 global $TCA, $LANG, $TYPO3_CONF_VARS;
1331
1332                         // Return blank, if disabled:
1333                 if ($this->dontShowClipControlPanels)   return '';
1334                 $cells=array();
1335
1336                 $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon;
1337
1338                         // Return blank, if disabled:
1339                         // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel:
1340                 if ($this->clipObj->current=='normal')  {       // For the "Normal" pad:
1341
1342                                 // Show copy/cut icons:
1343                         $isSel = (string)$this->clipObj->isSelected($table,$row['uid']);
1344                         $cells['copy']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'.
1345                                         '<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="" />'.
1346                                         '</a>';
1347                         $cells['cut']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'.
1348                                         '<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="" />'.
1349                                         '</a>';
1350
1351                 } else {        // For the numeric clipboard pads (showing checkboxes where one can select elements on/off)
1352
1353                                 // Setting name of the element in ->CBnames array:
1354                         $n=$table.'|'.$row['uid'];
1355                         $this->CBnames[]=$n;
1356
1357                                 // Check if the current element is selected and if so, prepare to set the checkbox as selected:
1358                         $checked = ($this->clipObj->isSelected($table,$row['uid'])?' checked="checked"':'');
1359
1360                                 // If the "duplicateField" value is set then select all elements which are duplicates...
1361                         if ($this->duplicateField && isset($row[$this->duplicateField]))        {
1362                                 $checked='';
1363                                 if (in_array($row[$this->duplicateField], $this->duplicateStack))       {
1364                                         $checked=' checked="checked"';
1365                                 }
1366                                 $this->duplicateStack[] = $row[$this->duplicateField];
1367                         }
1368
1369                                 // Adding the checkbox to the panel:
1370                         $cells['select']='<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />';
1371                 }
1372
1373                         // Now, looking for selected elements from the current table:
1374                 $elFromTable = $this->clipObj->elFromTable($table);
1375                 if (count($elFromTable) && $TCA[$table]['ctrl']['sortby'])      {       // IF elements are found and they can be individually ordered, then add a "paste after" icon:
1376                         $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,-$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'after',$elFromTable)).'">'.
1377                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteAfter',1).'" alt="" />'.
1378                                         '</a>';
1379                 }
1380
1381                         // Now, looking for elements in general:
1382                 $elFromTable = $this->clipObj->elFromTable('');
1383                 if ($table=='pages' && count($elFromTable))     {
1384                         $cells['pasteInto']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl('',$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'into',$elFromTable)).'">'.
1385                                         '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteinto.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteInto',1).'" alt="" />'.
1386                                         '</a>';
1387                 }
1388
1389                 /*
1390                  * @hook                        makeClip: Allows to change clip-icons of records in list-module
1391                  * @date                        2007-11-20
1392                  * @request             Bernhard Kraft  <krafbt@kraftb.at>
1393                  * @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.
1394                  */
1395                 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1396                         foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1397                                 $hookObject = t3lib_div::getUserObj($classData);
1398                                 if(!($hookObject instanceof localRecordList_actionsHook))       {
1399                                         throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567845);
1400                                 }
1401                                 $cells = $hookObject->makeClip($table, $row, $cells, $this);
1402                         }
1403                 }
1404
1405                         // Compile items into a DIV-element:
1406                 return '                                                        <!-- CLIPBOARD PANEL: '.$table.':'.$row['uid'].' -->
1407                                                                                         <div class="typo3-clipCtrl">'.implode('',$cells).'</div>';
1408         }
1409
1410         /**
1411          * Make reference count
1412          *
1413          * @param       string          Table name
1414          * @param       integer         UID of record
1415          * @return      string          HTML-table
1416          */
1417         function makeRef($table,$uid)   {
1418
1419                         // Compile information for title tag:
1420                 $infoData=array();
1421                 if (is_array($this->references)) {
1422                         foreach ($this->references as $row) {
1423                                 $infoData[]=$row['tablename'].':'.$row['recuid'].':'.$row['field'];
1424                         }
1425                 }
1426
1427                 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>' : '';
1428         }
1429
1430         /**
1431          * Creates the localization panel
1432          *
1433          * @param       string          The table
1434          * @param       array           The record for which to make the localization panel.
1435          * @return      array           Array with key 0/1 with content for column 1 and 2
1436          */
1437         function makeLocalizationPanel($table,$row)     {
1438                 global $TCA,$LANG;
1439
1440                 $out = array(
1441                         0 => '',
1442                         1 => '',
1443                 );
1444
1445                 $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList);
1446                 $this->translations = $translations['translations'];
1447
1448                         // Language title and icon:
1449                 $out[0] = $this->languageFlag($row[$TCA[$table]['ctrl']['languageField']]);
1450
1451                 if (is_array($translations))    {
1452
1453                                 // Traverse page translations and add icon for each language that does NOT yet exist:
1454                         $lNew = '';
1455                         foreach($this->pageOverlays as $lUid_OnPage => $lsysRec)        {
1456                                 if (!isset($translations['translations'][$lUid_OnPage]) && $GLOBALS['BE_USER']->checkLanguageAccess($lUid_OnPage))      {
1457                                         $href = $GLOBALS['TBE_TEMPLATE']->issueCommand(
1458                                                 '&cmd['.$table.']['.$row['uid'].'][localize]='.$lUid_OnPage,
1459                                                 $this->listURL().'&justLocalized='.rawurlencode($table.':'.$row['uid'].':'.$lUid_OnPage)
1460                                         );
1461
1462                                         $lC = ($this->languageIconTitles[$lUid_OnPage]['flagIcon'] ? '<img src="'.$this->languageIconTitles[$lUid_OnPage]['flagIcon'].'" class="absmiddle" alt="" />' : $this->languageIconTitles[$lUid_OnPage]['title']);
1463                                         $lC = '<a href="'.htmlspecialchars($href).'">'.$lC.'</a> ';
1464
1465                                         $lNew.=$lC;
1466                                 }
1467                         }
1468
1469                         if ($lNew)      $out[1].= $lNew;
1470                 } else {
1471                         $out[0] = '&nbsp;&nbsp;&nbsp;&nbsp;'.$out[0];
1472                 }
1473
1474
1475                 return $out;
1476         }
1477
1478         /**
1479          * Create the selector box for selecting fields to display from a table:
1480          *
1481          * @param       string          Table name
1482          * @param       boolean         If true, form-fields will be wrapped around the table.
1483          * @return      string          HTML table with the selector box (name: displayFields['.$table.'][])
1484          */
1485         function fieldSelectBox($table,$formFields=1)   {
1486                 global $TCA, $LANG;
1487
1488                         // Init:
1489                 t3lib_div::loadTCA($table);
1490                 $formElements=array('','');
1491                 if ($formFields)        {
1492                         $formElements=array('<form action="'.htmlspecialchars($this->listURL()).'" method="post">','</form>');
1493                 }
1494
1495                         // Load already selected fields, if any:
1496                 $setFields=is_array($this->setFields[$table]) ? $this->setFields[$table] : array();
1497
1498                         // Request fields from table:
1499                 $fields = $this->makeFieldList($table, false, true);
1500
1501                         // Add pseudo "control" fields
1502                 $fields[]='_PATH_';
1503                 $fields[]='_REF_';
1504                 $fields[]='_LOCALIZATION_';
1505                 $fields[]='_CONTROL_';
1506                 $fields[]='_CLIPBOARD_';
1507
1508                         // Create an option for each field:
1509                 $opt=array();
1510                 $opt[] = '<option value=""></option>';
1511                 foreach($fields as $fN) {
1512                         $fL = is_array($TCA[$table]['columns'][$fN]) ? rtrim($LANG->sL($TCA[$table]['columns'][$fN]['label']),':') : '['.$fN.']';       // Field label
1513                         $opt[] = '
1514                                                                                         <option value="'.$fN.'"'.(in_array($fN,$setFields)?' selected="selected"':'').'>'.htmlspecialchars($fL).'</option>';
1515                 }
1516
1517                         // Compile the options into a multiple selector box:
1518                 $lMenu = '
1519                                                                                 <select size="'.t3lib_div::intInRange(count($fields)+1,3,20).'" multiple="multiple" name="displayFields['.$table.'][]">'.implode('',$opt).'
1520                                                                                 </select>
1521                                 ';
1522
1523                         // Table with the field selector::
1524                 $content.= '
1525                         '.$formElements[0].'
1526
1527                                 <!--
1528                                         Field selector for extended table view:
1529                                 -->
1530                                 <table border="0" cellpadding="0" cellspacing="0" class="bgColor4" id="typo3-dblist-fieldSelect">
1531                                         <tr>
1532                                                 <td>'.$lMenu.'</td>
1533                                                 <td><input type="submit" name="search" value="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.setFields',1).'" /></td>
1534                                         </tr>
1535                                 </table>
1536                         '.$formElements[1];
1537                 return $content;
1538         }
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550         /*********************************
1551          *
1552          * Helper functions
1553          *
1554          *********************************/
1555
1556         /**
1557          * Creates a link around $string. The link contains an onclick action which submits the script with some clipboard action.
1558          * Currently, this is used for setting elements / delete elements.
1559          *
1560          * @param       string          The HTML content to link (image/text)
1561          * @param       string          Table name
1562          * @param       string          Clipboard command (eg. "setCB" or "delete")
1563          * @param       string          Warning text, if any ("delete" uses this for confirmation)
1564          * @return      string          <a> tag wrapped link.
1565          */
1566         function linkClipboardHeaderIcon($string,$table,$cmd,$warning='')       {
1567                 $onClickEvent = 'document.dblistForm.cmd.value=\''.$cmd.'\';document.dblistForm.cmd_table.value=\''.$table.'\';document.dblistForm.submit();';
1568                 if ($warning)   $onClickEvent = 'if (confirm('.$GLOBALS['LANG']->JScharCode($warning).')){'.$onClickEvent.'}';
1569                 return '<a href="#" onclick="'.htmlspecialchars($onClickEvent.'return false;').'">'.$string.'</a>';
1570         }
1571
1572         /**
1573          * Returns true if a numeric clipboard pad is selected/active
1574          *
1575          * @return      boolean
1576          */
1577         function clipNumPane()  {
1578                 return in_Array('_CLIPBOARD_',$this->fieldArray) && $this->clipObj->current!='normal';
1579         }
1580
1581         /**
1582          * Creates a sort-by link on the input string ($code).
1583          * It will automatically detect if sorting should be ascending or descending depending on $this->sortRev.
1584          * Also some fields will not be possible to sort (including if single-table-view is disabled).
1585          *
1586          * @param       string          The string to link (text)
1587          * @param       string          The fieldname represented by the title ($code)
1588          * @param       string          Table name
1589          * @return      string          Linked $code variable
1590          */
1591         function addSortLink($code,$field,$table)       {
1592
1593                         // Certain circumstances just return string right away (no links):
1594                 if ($field=='_CONTROL_' || $field=='_LOCALIZATION_' || $field=='_CLIPBOARD_' || $field=='_REF_' || $this->disableSingleTableView)       return $code;
1595
1596                         // If "_PATH_" (showing record path) is selected, force sorting by pid field (will at least group the records!)
1597                 if ($field=='_PATH_')   $field=pid;
1598
1599                         //       Create the sort link:
1600                 $sortUrl = $this->listURL('',-1,'sortField,sortRev,table').'&table='.$table.'&sortField='.$field.'&sortRev='.($this->sortRev || ($this->sortField!=$field)?0:1);
1601                 $sortArrow = ($this->sortField==$field?'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/red'.($this->sortRev?'up':'down').'.gif','width="7" height="4"').' alt="" />':'');
1602
1603                         // Return linked field:
1604                 return '<a href="'.htmlspecialchars($sortUrl).'">'.$code.
1605                                 $sortArrow.
1606                                 '</a>';
1607         }
1608
1609         /**
1610          * Returns the path for a certain pid
1611          * The result is cached internally for the session, thus you can call this function as much as you like without performance problems.
1612          *
1613          * @param       integer         The page id for which to get the path
1614          * @return      string          The path.
1615          */
1616         function recPath($pid)  {
1617                 if (!isset($this->recPath_cache[$pid])) {
1618                         $this->recPath_cache[$pid] = t3lib_BEfunc::getRecordPath($pid,$this->perms_clause,20);
1619                 }
1620                 return $this->recPath_cache[$pid];
1621         }
1622
1623         /**
1624          * Returns true if a link for creating new records should be displayed for $table
1625          *
1626          * @param       string          Table name
1627          * @return      boolean         Returns true if a link for creating new records should be displayed for $table
1628          * @see         SC_db_new::showNewRecLink
1629          */
1630         function showNewRecLink($table) {
1631                         // No deny/allow tables are set:
1632                 if (!count($this->allowedNewTables) && !count($this->deniedNewTables)) {
1633                         return true;
1634                         // If table is not denied (which takes precedence over allowed tables):
1635                 } elseif (!in_array($table, $this->deniedNewTables) && (!count($this->allowedNewTables) || in_array($table, $this->allowedNewTables))) {
1636                         return true;
1637                         // If table is denied or allowed tables are set, but table is not part of:
1638                 } else {
1639                         return false;
1640                 }
1641         }
1642
1643         /**
1644          * 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.
1645          * Uses REQUEST_URI as value.
1646          *
1647          * @return      string
1648          */
1649         function makeReturnUrl()        {
1650                 return '&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
1651         }
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663         /************************************
1664          *
1665          * CSV related functions
1666          *
1667          ************************************/
1668
1669         /**
1670          * Initializes internal csvLines array with the header of field names
1671          *
1672          * @return      void
1673          */
1674         function initCSV()      {
1675
1676                         // Reset:
1677                 $this->csvLines=array();
1678
1679                         // Getting header line with field names:
1680                 $csvRow = array();
1681                 foreach ($this->fieldArray as $fN) {
1682                         if ($fN == '_CONTROL_' || $fN == '_CLIPBOARD_') {
1683                                         continue;
1684                         }
1685                         $csvRow[] = $fN;
1686                 }
1687
1688                         // Set the header + an empty row:
1689                 $this->setCsvRow($csvRow);
1690                 $this->csvLines[] = '';
1691         }
1692
1693
1694         /**
1695          * Adds the content of input array $row to the CSV list:
1696          *
1697          * @param       array           Record array, from which the values of fields found in $this->fieldArray will be listed in the CSV output.
1698          * @param       string          Table name
1699          * @return      void
1700          */
1701         function addToCSV($row,$table)  {
1702
1703                         // Traversing fields, adding values from $row:
1704                 $csvRow = array();
1705                 foreach ($this->fieldArray as $fN) {
1706                         switch ($fN) {
1707                                 case '_PATH':
1708                                         $csvRow[] = $this->recPath($row['pid']);
1709                                         break;
1710
1711                                 case '_REF_':
1712                                         $csvRow[] = $this->makeRef($table, $row['uid']);
1713                                         break;
1714
1715                                         // remove these columns from the CSV view
1716                                 case '_CONTROL_':
1717                                 case '_CLIPBOARD_':
1718                                         continue;
1719                                         break;
1720
1721                                 default:
1722                                         $csvRow[] = $row[$fN];
1723                         }
1724                 }
1725
1726                         // Set the values in the CSV list
1727                 $this->setCsvRow($csvRow);
1728         }
1729
1730
1731         /**
1732          * Adds input row of values to the internal csvLines array as a CSV formatted line
1733          *
1734          * @param       array           Array with values to be listed.
1735          * @return      void
1736          */
1737         function setCsvRow($csvRow)     {
1738                 $this->csvLines[] = t3lib_div::csvValues($csvRow);
1739         }
1740
1741         /**
1742          * Compiles the internal csvLines array to a csv-string and outputs it to the browser.
1743          * This function exits!
1744          *
1745          * @param       string          Filename prefix:
1746          * @return      void            EXITS php execusion!
1747          */
1748         function outputCSV($prefix)     {
1749
1750                         // Setting filename:
1751                 $filename=$prefix.'_'.date('dmy-Hi').'.csv';
1752
1753                         // Creating output header:
1754                 $mimeType = 'application/octet-stream';
1755                 Header('Content-Type: '.$mimeType);
1756                 Header('Content-Disposition: attachment; filename='.$filename);
1757
1758                         // Printing the content of the CSV lines:
1759                 echo implode(chr(13).chr(10),$this->csvLines);
1760
1761                         // Exits:
1762                 exit;
1763         }
1764 }
1765
1766
1767
1768 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc'])   {
1769         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']);
1770 }
1771
1772 ?>