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