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