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