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