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