2 /*************************************************************
5 * (c) 1999-2009 Kasper Skårhøj (kasperYYYY@typo3.com)
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.
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.
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.
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
28 * Include file extending recordList which extended t3lib_recordList
29 * Used specifically for the Web>List module (db_list.php)
31 * Revised for TYPO3 3.6 December/2003 by Kasper Skårhøj
34 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
47 * Class for rendering of Web>List module
49 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
53 class localRecordList extends recordList {
56 var $alternateBgColors=FALSE; // If TRUE, table rows in the list will alternate in background colors (and have background colors at all!)
57 var $allowedNewTables=array(); // Used to indicate which tables (values in the array) that can have a create-new-record link. If the array is empty, all tables are allowed.
58 var $deniedNewTables=array(); // Used to indicate which tables (values in the array) that cannot have a create-new-record link. If the array is empty, all tables are allowed.
59 var $newWizards=FALSE; // If TRUE, the control panel will contain links to the create-new wizards for pages and tt_content elements (normally, the link goes to just creating a new element without the wizards!).
61 var $dontShowClipControlPanels=FALSE; // If TRUE, will disable the rendering of clipboard + control panels.
62 var $showClipboard=FALSE; // If TRUE, will show the clipboard in the field list.
63 var $noControlPanels = FALSE; // If TRUE, will DISABLE all control panels in lists. (Takes precedence)
64 var $clickMenuEnabled = TRUE; // If TRUE, clickmenus will be rendered
66 var $totalRowCount; // count of record rows in view
68 var $spaceIcon; // space icon used for alignment
71 var $pageRow=array(); // Set to the page record (see writeTop())
73 // Used to accumulate CSV lines for CSV export.
74 protected $csvLines = array();
76 var $csvOutput=FALSE; // If set, the listing is returned as CSV instead.
81 * @var t3lib_clipboard
84 var $CBnames=array(); // Tracking names of elements (for clipboard use)
85 var $duplicateStack=array(); // Used to track which elements has duplicates and how many
88 * [$tablename][$uid] = number of references to this record
92 protected $referenceCount = array();
94 var $translations; // Translations of the current record
95 var $selFieldList; // select fields for the query which fetches the translations of the current record
97 public $disableSingleTableView = FALSE;
99 public function __construct() {
100 parent::__construct();
104 * Create the panel of buttons for submitting the form or otherwise perform operations.
106 * @return array all available buttons as an assoc. array
108 public function getButtons() {
126 // Get users permissions for this page record:
127 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms($this->pageRow);
130 if (!strlen($this->id)) {
131 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_noId', $GLOBALS['BACK_PATH'], '', TRUE);
132 } elseif(!$this->id) {
133 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_root', $GLOBALS['BACK_PATH'], '', TRUE);
135 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module', $GLOBALS['BACK_PATH'], '', TRUE);
138 if (isset($this->id)) {
139 // View Exclude doktypes 254,255 Configuration: mod.web_list.noViewWithDokTypes = 254,255
140 if (isset($GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'])) {
141 $noViewDokTypes = t3lib_div::trimExplode(',', $GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'], TRUE);
143 //default exclusion: doktype 254 (folder), 255 (recycler)
144 $noViewDokTypes = array(t3lib_pageSelect::DOKTYPE_SYSFOLDER, t3lib_pageSelect::DOKTYPE_RECYCLER);
147 if (!in_array($this->pageRow['doktype'], $noViewDokTypes)) {
148 $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) . '">' .
149 t3lib_iconWorks::getSpriteIcon('actions-document-view') .
154 if (!$GLOBALS['SOBE']->modTSconfig['properties']['noCreateRecordsLink']) {
155 $buttons['new_record'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'db_new.php?id=' . $this->id . '\');') . '" title="' . $GLOBALS['LANG']->getLL('newRecordGeneral', TRUE) . '">' .
156 t3lib_iconWorks::getSpriteIcon('actions-document-new') .
160 // If edit permissions are set (see class.t3lib_userauthgroup.php)
161 if ($localCalcPerms&2 && !empty($this->id)) {
164 $params = '&edit[pages][' . $this->pageRow['uid'] . ']=edit';
165 $buttons['edit'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) . '" title="' . $GLOBALS['LANG']->getLL('editPage', TRUE) . '">' .
166 t3lib_iconWorks::getSpriteIcon('actions-page-open') .
171 if (($localCalcPerms&8) || ($localCalcPerms&16)) {
172 $elFromTable = $this->clipObj->elFromTable('');
173 if (count($elFromTable)) {
174 $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) . '">' .
175 t3lib_iconWorks::getSpriteIcon('actions-document-paste-after') .
181 $buttons['cache'] = '<a href="' . htmlspecialchars($this->listURL() . '&clear_cache=1') . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.clear_cache', TRUE) . '">' .
182 t3lib_iconWorks::getSpriteIcon('actions-system-cache-clear') .
188 $buttons['csv'] = '<a href="' . htmlspecialchars($this->listURL() . '&csv=1') . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.csv', TRUE) . '">' .
189 t3lib_iconWorks::getSpriteIcon('mimetypes-text-csv') .
193 if (t3lib_extMgm::isLoaded('impexp')) {
194 $url = $this->backPath . t3lib_extMgm::extRelPath('impexp') . 'app/index.php?tx_impexp[action]=export';
195 $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) . '">' .
196 t3lib_iconWorks::getSpriteIcon('actions-document-export-t3d') .
203 $buttons['reload'] = '<a href="' . htmlspecialchars($this->listURL()) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.reload', TRUE) . '">' .
204 t3lib_iconWorks::getSpriteIcon('actions-system-refresh') .
208 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
209 $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');
213 if ($this->returnUrl) {
214 $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) . '">' .
215 t3lib_iconWorks::getSpriteIcon('actions-view-go-back') .
224 * Creates the listing of records from a single table
226 * @param string Table name
227 * @param integer Page id
228 * @param string List of fields to show in the listing. Pseudo fields will be added including the record header.
229 * @return string HTML table with the listing for the record.
231 function getTable($table,$id,$rowlist) {
232 // Loading all TCA details for this table:
233 t3lib_div::loadTCA($table);
237 $titleCol = $GLOBALS['TCA'][$table]['ctrl']['label'];
238 $thumbsCol = $GLOBALS['TCA'][$table]['ctrl']['thumbnail'];
239 $l10nEnabled = $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
240 && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'];
241 $tableCollapsed = (!$this->tablesCollapsed[$table]) ? FALSE : TRUE;
243 // prepare space icon
244 $this->spaceIcon = t3lib_iconWorks::getSpriteIcon('empty-empty', array('style' => 'background-position: 0 10px;'));
246 // Cleaning rowlist for duplicates and place the $titleCol as the first column always!
247 $this->fieldArray=array();
249 $this->fieldArray[] = $titleCol; // Add title column
251 if (!t3lib_div::inList($rowlist,'_CONTROL_')) {
252 $this->fieldArray[] = '_CONTROL_';
253 $this->fieldArray[] = '_AFTERCONTROL_';
256 if ($this->showClipboard) {
257 $this->fieldArray[] = '_CLIPBOARD_';
260 if (!$this->dontShowClipControlPanels) {
261 $this->fieldArray[]='_REF_';
262 $this->fieldArray[]='_AFTERREF_';
265 if ($this->searchLevels) {
266 $this->fieldArray[]='_PATH_';
269 if ($this->localizationView && $l10nEnabled) {
270 $this->fieldArray[] = '_LOCALIZATION_';
271 $this->fieldArray[] = '_LOCALIZATION_b';
273 ' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '<=0
275 ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . ' = 0
279 $this->fieldArray=array_unique(array_merge($this->fieldArray,t3lib_div::trimExplode(',',$rowlist,1)));
280 if ($this->noControlPanels) {
281 $tempArray = array_flip($this->fieldArray);
282 unset($tempArray['_CONTROL_']);
283 unset($tempArray['_CLIPBOARD_']);
284 $this->fieldArray = array_keys($tempArray);
287 // Creating the list of fields to include in the SQL query:
288 $selectFields = $this->fieldArray;
289 $selectFields[] = 'uid';
290 $selectFields[] = 'pid';
291 if ($thumbsCol) $selectFields[] = $thumbsCol; // adding column for thumbnails
292 if ($table=='pages') {
293 if (t3lib_extMgm::isLoaded('cms')) {
294 $selectFields[] = 'module';
295 $selectFields[] = 'extendToSubpages';
296 $selectFields[] = 'nav_hide';
298 $selectFields[] = 'doktype';
300 if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
301 $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
303 if ($GLOBALS['TCA'][$table]['ctrl']['type']) {
304 $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['type'];
306 if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
307 $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
309 if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
310 $selectFields[] = 't3ver_id';
311 $selectFields[] = 't3ver_state';
312 $selectFields[] = 't3ver_wsid';
313 $selectFields[] = 't3ver_swapmode'; // Filtered out when pages in makeFieldList()
316 $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
317 $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
319 if ($GLOBALS['TCA'][$table]['ctrl']['label_alt']) {
320 $selectFields = array_merge(
322 t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['label_alt'], 1)
325 $selectFields = array_unique($selectFields); // Unique list!
326 $fieldListFields = $this->makeFieldList($table, 1);
327 if (empty($fieldListFields) && $GLOBALS['TYPO3_CONF_VARS']['BE']['debug']) {
330 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.php:missingTcaColumnsMessage', TRUE),
334 $messageTitle = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.php:missingTcaColumnsMessageTitle', TRUE);
336 $flashMessage = t3lib_div::makeInstance(
337 't3lib_FlashMessage',
340 t3lib_FlashMessage::WARNING,
343 /** @var t3lib_FlashMessage $flashMessage */
344 t3lib_FlashMessageQueue::addMessage($flashMessage);
346 $selectFields = array_intersect($selectFields, $fieldListFields); // Making sure that the fields in the field-list ARE in the field-list from TCA!
347 $selFieldList = implode(',', $selectFields); // implode it into a list of fields for the SQL-statement.
348 $this->selFieldList = $selFieldList;
351 * @hook DB-List getTable
353 * @request Malte Jansen <mail@maltejansen.de>
355 if(is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) {
356 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) {
357 $hookObject = t3lib_div::getUserObj($classData);
359 if(!($hookObject instanceof t3lib_localRecordListGetTableHook)) {
360 throw new UnexpectedValueException('$hookObject must implement interface t3lib_localRecordListGetTableHook', 1195114460);
363 $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this);
367 // Create the SQL query for selecting the elements in the listing:
368 if ($this->csvOutput) { // do not do paging when outputting as CSV
372 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
373 // Get the two previous rows for sorting if displaying page > 1
374 $this->firstElementNumber = $this->firstElementNumber - 2;
375 $this->iLimit = $this->iLimit + 2;
376 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc)
377 $this->firstElementNumber = $this->firstElementNumber + 2;
378 $this->iLimit = $this->iLimit - 2;
380 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc)
383 $this->setTotalItems($queryParts); // Finding the total amount of records on the page (API function from class.db_list.inc)
388 $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table;
390 // If the count query returned any number of records, we perform the real query, selecting records.
391 if ($this->totalItems) {
392 // Fetch records only if not in single table mode or if in multi table mode and not collapsed
393 if ($listOnlyInSingleTableMode || (!$this->table && $tableCollapsed)) {
394 $dbCount = $this->totalItems;
396 // set the showLimit to the number of records when outputting as CSV
397 if ($this->csvOutput) {
398 $this->showLimit = $this->totalItems;
399 $this->iLimit = $this->totalItems;
401 $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
402 $dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result);
406 // If any records was selected, render the list:
409 // Half line is drawn between tables:
410 if (!$listOnlyInSingleTableMode) {
412 if (!$this->table && !$rowlist) {
413 $theData[$titleCol] = '<img src="clear.gif" width="'.($GLOBALS['SOBE']->MOD_SETTINGS['bigControlPanel']?'230':'350').'" height="1" alt="" />';
414 if (in_array('_CONTROL_',$this->fieldArray)) $theData['_CONTROL_']='';
415 if (in_array('_CLIPBOARD_',$this->fieldArray)) $theData['_CLIPBOARD_']='';
417 $out.=$this->addelement(0,'',$theData,'class="c-table-row-spacer"',$this->leftMargin);
420 $tableTitle = $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title'], TRUE);
421 if ($tableTitle === '') {
422 $tableTitle = $table;
424 // Header line is drawn
426 if ($this->disableSingleTableView) {
427 $theData[$titleCol] = '<span class="c-table">' .
428 t3lib_BEfunc::wrapInHelp($table, '', $tableTitle) .
429 '</span> (' . $this->totalItems . ')';
431 $theData[$titleCol] = $this->linkWrapTable($table, '<span class="c-table">' . $tableTitle . '</span> (' . $this->totalItems . ') ' .
432 ($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))))
436 if ($listOnlyInSingleTableMode) {
439 <td class="t3-row-header" style="width:95%;">' . t3lib_BEfunc::wrapInHelp($table, '', $theData[$titleCol]) . '</td>
442 // Render collapse button if in multi table mode
445 $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)) . '">' .
446 ($tableCollapsed ? t3lib_iconWorks::getSpriteIcon('actions-view-list-expand', array('class' => 'collapseIcon')) : t3lib_iconWorks::getSpriteIcon('actions-view-list-collapse', array('class' => 'collapseIcon'))) .
449 $out .= $this->addElement(1, $collapseIcon, $theData, ' class="t3-row-header"', '');
452 // Render table rows only if in multi table view and not collapsed or if in single table view
453 if (!$listOnlyInSingleTableMode && (!$tableCollapsed || $this->table)) {
454 // Fixing a order table for sortby tables
455 $this->currentTable = array();
456 $currentIdList = array();
457 $doSort = ($GLOBALS['TCA'][$table]['ctrl']['sortby'] && !$this->sortField);
462 // Get first two rows and initialize prevPrevUid and prevUid if on page > 1
463 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
464 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
465 $prevPrevUid = -(int) $row['uid'];
466 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
467 $prevUid = $row['uid'];
470 $accRows = array(); // Accumulate rows here
471 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
473 if (!$this->isRowListingConditionFulfilled($table, $row)) {
477 // In offline workspace, look for alternative record:
478 t3lib_BEfunc::workspaceOL($table, $row, $GLOBALS['BE_USER']->workspace, TRUE);
480 if (is_array($row)) {
482 $currentIdList[] = $row['uid'];
485 $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
486 $this->currentTable['next'][$prevUid] = '-'.$row['uid'];
487 $this->currentTable['prevUid'][$row['uid']] = $prevUid;
489 $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
490 $prevUid=$row['uid'];
494 $GLOBALS['TYPO3_DB']->sql_free_result($result);
496 $this->totalRowCount = count($accRows);
499 if ($this->csvOutput) $this->initCSV();
502 $this->CBnames=array();
503 $this->duplicateStack=array();
504 $this->eCounter=$this->firstElementNumber;
509 foreach($accRows as $row) {
510 // Render item row if counter < limit
511 if ($cc < $this->iLimit) {
513 $this->translations = FALSE;
514 $iOut.= $this->renderListRow($table,$row,$cc,$titleCol,$thumbsCol);
516 // If localization view is enabled it means that the selected records are either default or All language and here we will not select translations which point to the main record:
517 if ($this->localizationView && $l10nEnabled) {
518 // For each available translation, render the record:
519 if (is_array($this->translations)) {
520 foreach ($this->translations as $lRow) {
521 // $lRow isn't always what we want - if record was moved we've to work with the placeholder records otherwise the list is messed up a bit
522 if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) {
523 $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);
524 $lRow = is_array($tmpRow)?$tmpRow:$lRow;
526 // In offline workspace, look for alternative record:
527 t3lib_BEfunc::workspaceOL($table, $lRow, $GLOBALS['BE_USER']->workspace, TRUE);
528 if (is_array($lRow) && $GLOBALS['BE_USER']->checkLanguageAccess($lRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
529 $currentIdList[] = $lRow['uid'];
530 $iOut.=$this->renderListRow($table,$lRow,$cc,$titleCol,$thumbsCol,18);
537 // Counter of total rows incremented:
541 // Record navigation is added to the beginning and end of the table if in single table mode
543 $iOut = $this->renderListNavigation('top') . $iOut . $this->renderListNavigation('bottom');
545 // show that there are more records than shown
546 if ($this->totalItems > $this->itemsLimitPerTable) {
547 $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems;
548 $hasMore = ($this->totalItems > $this->itemsLimitSingleTable);
549 $iOut .= '<tr><td colspan="' . count($this->fieldArray) . '" style="padding:5px;">
550 <a href="'.htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '">' .
551 '<img' . t3lib_iconWorks::skinImg($this->backPath,'gfx/pildown.gif', 'width="14" height="14"') .' alt="" />'.
552 ' <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a>
558 // The header row for the table is now created:
559 $out .= $this->renderListHeader($table,$currentIdList);
562 // The list of records is added after the header:
566 // ... and it is all wrapped in a table:
572 DB listing of elements: "'.htmlspecialchars($table).'"
574 <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist'.($listOnlyInSingleTableMode?' typo3-dblist-overview':'').'">
579 if ($this->csvOutput) $this->outputCSV($table); // This ends the page with exit.
588 * Check if all row listing conditions are fulfilled.
590 * This function serves as a dummy method to be overriden in extending classes.
592 * @param string $table Table name
593 * @param array $row Record
594 * @return bool True, if all conditions are fulfilled.
596 protected function isRowListingConditionFulfilled($table, $row) {
601 * Rendering a single row for the list
603 * @param string Table name
604 * @param array Current record
605 * @param integer Counter, counting for each time an element is rendered (used for alternating colors)
606 * @param string Table field (column) where header value is found
607 * @param string Table field (column) where (possible) thumbnails can be found
608 * @param integer Indent from left.
609 * @return string Table row for the element
613 function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0) {
616 if (strlen($this->searchString)) { // If in search mode, make sure the preview will show the correct page
617 $id_orig = $this->id;
618 $this->id = $row['pid'];
621 if (is_array($row)) {
622 // add special classes for first and last row
624 if ($cc == 1 && $indent == 0) {
625 $rowSpecial .= ' firstcol';
627 if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
628 $rowSpecial .= ' lastcol';
631 // Background color, if any:
632 if ($this->alternateBgColors) {
633 $row_bgColor = ($cc%2) ? ' class="db_list_normal'.$rowSpecial.'"' : ' class="db_list_alt'.$rowSpecial.'"';
635 $row_bgColor = ' class="db_list_normal'.$rowSpecial.'"';
637 // Overriding with versions background color if any:
638 $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor;
643 // The icon with link
644 $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table);
645 $iconImg = t3lib_iconWorks::getSpriteIconForRecord($table, $row, array('title' => htmlspecialchars($alttext), 'style' => ($indent ? ' margin-left: ' . $indent . 'px;' : '')));
648 $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg;
650 // Preparing and getting the data-array
652 foreach($this->fieldArray as $fCol) {
653 if ($fCol==$titleCol) {
654 $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
655 // If the record is edit-locked by another user, we will show a little warning sign:
656 if (($lockInfo = t3lib_BEfunc::isRecordLocked($table, $row['uid']))) {
657 $warning = '<a href="#" onclick="' . htmlspecialchars('alert(' . $GLOBALS['LANG']->JScharCode($lockInfo['msg']) . '); return false;') . '" title="' . htmlspecialchars($lockInfo['msg']) . '">' .
658 t3lib_iconWorks::getSpriteIcon('status-warning-in-use') .
661 $theData[$fCol] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row);
663 // Render thumbsnails if a thumbnail column exists and there is content in it:
664 if ($this->thumbs && trim($row[$thumbsCol])) {
665 $theData[$fCol] .= '<br />' . $this->thumbCode($row,$table,$thumbsCol);
668 $localizationMarkerClass = '';
669 if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField'])
670 && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0
671 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) {
672 // it's a translated record with a language parent
673 $localizationMarkerClass = ' localization';
675 } elseif ($fCol == 'pid') {
676 $theData[$fCol]=$row[$fCol];
677 } elseif ($fCol == '_PATH_') {
678 $theData[$fCol]=$this->recPath($row['pid']);
679 } elseif ($fCol == '_REF_') {
680 $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']);
681 } elseif ($fCol == '_CONTROL_') {
682 $theData[$fCol]=$this->makeControl($table,$row);
683 } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') {
684 $theData[$fCol] = ' ';
685 } elseif ($fCol == '_CLIPBOARD_') {
686 $theData[$fCol]=$this->makeClip($table,$row);
687 } elseif ($fCol == '_LOCALIZATION_') {
688 list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row);
689 $theData[$fCol] = $lC1;
690 $theData[$fCol.'b'] = $lC2;
691 } elseif ($fCol == '_LOCALIZATION_b') {
692 // Do nothing, has been done above.
694 $tmpProc = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']);
695 $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
696 if ($this->csvOutput) {
697 $row[$fCol] = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']);
702 if (strlen($this->searchString)) { // Reset the ID if it was overwritten
703 $this->id = $id_orig;
706 // Add row to CSV list:
707 if ($this->csvOutput) {
708 $this->addToCSV($row,$table);
711 // Add classes to table cells
712 $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass;
713 if (!$this->dontShowClipControlPanels) {
714 $this->addElement_tdCssClass['_CONTROL_'] = 'col-control';
715 $this->addElement_tdCssClass['_AFTERCONTROL_'] = 'col-control-space';
716 $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard';
718 $this->addElement_tdCssClass['_PATH_'] = 'col-path';
719 $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa';
720 $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb';
722 // Create element in table cells:
723 $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor);
725 // Finally, return table row element:
731 * Gets the number of records referencing the record with the UID $uid in
732 * the table $tableName.
734 * @param string $tableName
735 * table name of the referenced record, must not be empty
736 * @param integer $uid
737 * UID of the referenced record, must be > 0
739 * @return integer the number of references to record $uid in table
740 * $tableName, will be >= 0
742 protected function getReferenceCount($tableName, $uid) {
743 if (!isset($this->referenceCount[$tableName][$uid])) {
744 $numberOfReferences = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
747 'ref_table = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr(
748 $tableName, 'sys_refindex'
750 ' AND ref_uid = ' . $uid .
754 $this->referenceCount[$tableName][$uid] = $numberOfReferences;
757 return $this->referenceCount[$tableName][$uid];
761 * Rendering the header row for a table
763 * @param string Table name
764 * @param array Array of the currently displayed uids of the table
765 * @return string Header table row
769 function renderListHeader($table, $currentIdList) {
773 // Traverse the fields:
774 foreach($this->fieldArray as $fCol) {
776 // Calculate users permissions to edit records in the table:
777 $permsEdit = $this->calcPerms & ($table=='pages'?2:16);
779 switch((string)$fCol) {
780 case '_PATH_': // Path
781 $theData[$fCol] = '<i>[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels._PATH_', 1) . ']</i>';
783 case '_REF_': // References
784 $theData[$fCol] = '<i>[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_file_list.xml:c__REF_', 1) . ']</i>';
786 case '_LOCALIZATION_': // Path
787 $theData[$fCol] = '<i>[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels._LOCALIZATION_', 1) . ']</i>';
789 case '_LOCALIZATION_b': // Path
790 $theData[$fCol] = $GLOBALS['LANG']->getLL('Localize', 1);
792 case '_CLIPBOARD_': // Clipboard:
795 // If there are elements on the clipboard for this table, then display the "paste into" icon:
796 $elFromTable = $this->clipObj->elFromTable($table);
797 if (count($elFromTable)) {
798 $cells['pasteAfter'] = '<a href="' . htmlspecialchars($this->clipObj->pasteUrl($table, $this->id)) .
799 '" onclick="' . htmlspecialchars('return ' . $this->clipObj->confirmMsg('pages', $this->pageRow, 'into' ,$elFromTable)) .
800 '" title="' . $GLOBALS['LANG']->getLL('clip_paste', TRUE) . '">' .
801 t3lib_iconWorks::getSpriteIcon('actions-document-paste-after') . '</a>';
804 // If the numeric clipboard pads are enabled, display the control icons for that:
805 if ($this->clipObj->current!='normal') {
807 // The "select" link:
808 $cells['copyMarked'] = $this->linkClipboardHeaderIcon(
809 t3lib_iconWorks::getSpriteIcon(
811 array('title' => $GLOBALS['LANG']->getLL('clip_selectMarked', TRUE))
816 // The "edit marked" link:
817 $editIdList = implode(',',$currentIdList);
818 $editIdList = "'+editList('".$table."','".$editIdList."')+'";
819 $params='&edit['.$table.']['.$editIdList.']=edit&disHelp=1';
820 $cells['edit'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath, -1)) .
821 '" title="' . $GLOBALS['LANG']->getLL('clip_editMarked', TRUE) . '">' .
822 t3lib_iconWorks::getSpriteIcon('actions-document-open') .
825 // The "Delete marked" link:
826 $cells['delete'] = $this->linkClipboardHeaderIcon(
827 t3lib_iconWorks::getSpriteIcon(
828 'actions-edit-delete',
829 array('title' => $GLOBALS['LANG']->getLL('clip_deleteMarked', TRUE))
833 sprintf($GLOBALS['LANG']->getLL('clip_deleteMarkedWarning'), $GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['ctrl']['title']))
836 // The "Select all" link:
837 $cells['markAll'] = '<a class="cbcCheckAll" rel="" href="#" onclick="' .
838 htmlspecialchars('checkOffCB(\'' . implode(',', $this->CBnames) . '\', this); return false;') .
839 '" title="' . $GLOBALS['LANG']->getLL('clip_markRecords', TRUE) . '">' .
840 t3lib_iconWorks::getSpriteIcon('actions-document-select') .
846 * @hook renderListHeaderActions: Allows to change the clipboard icons of the Web>List table headers
848 * @request Bernhard Kraft <krafbt@kraftb.at>
849 * @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.
851 if(is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
852 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
853 $hookObject = t3lib_div::getUserObj($classData);
854 if(!($hookObject instanceof localRecordList_actionsHook)) {
855 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567850);
857 $cells = $hookObject->renderListHeaderActions($table, $currentIdList, $cells, $this);
860 $theData[$fCol]=implode('',$cells);
862 case '_CONTROL_': // Control panel:
863 if (!$GLOBALS['TCA'][$table]['ctrl']['readOnly']) {
865 // If new records can be created on this page, add links:
866 if ($this->calcPerms&($table=='pages'?8:16) && $this->showNewRecLink($table)) {
867 if ($table=="tt_content" && $this->newWizards) {
868 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
869 $tmpTSc = t3lib_BEfunc::getModTSconfig($this->pageinfo['uid'],'mod.web_list');
870 $tmpTSc = $tmpTSc['properties']['newContentWiz.']['overrideWithExtension'];
871 $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';
873 $icon = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $newContentWizScriptPath . '?id=' . $this->id . '\');') . '" title="' . $GLOBALS['LANG']->getLL('new', TRUE) . '">'.
874 ($table == 'pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) .
876 } elseif ($table=='pages' && $this->newWizards) {
877 $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) . '">'.
878 ($table=='pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) .
882 $params = '&edit['.$table.']['.$this->id.']=new';
883 if ($table == 'pages_language_overlay') {
884 $params .= '&overrideVals[pages_language_overlay][doktype]=' . (int) $this->pageRow['doktype'];
886 $icon = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) . '" title="' . $GLOBALS['LANG']->getLL('new', TRUE) . '">'.
887 ($table=='pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) .
892 // If the table can be edited, add link for editing ALL SHOWN fields for all listed records:
893 if ($permsEdit && $this->table && is_array($currentIdList)) {
894 $editIdList = implode(',',$currentIdList);
895 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
896 $params = '&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.implode(',',$this->fieldArray).'&disHelp=1';
897 $icon .= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1 )) . '" title="' . $GLOBALS['LANG']->getLL('editShownColumns', TRUE) . '">' .
898 t3lib_iconWorks::getSpriteIcon('actions-document-open') .
901 // add an empty entry, so column count fits again after moving this into $icon
902 $theData[$fCol] = ' ';
905 case '_AFTERCONTROL_': // space column
906 case '_AFTERREF_': // space column
907 $theData[$fCol] = ' ';
909 default: // Regular fields header:
911 if ($this->table && is_array($currentIdList)) {
913 // If the numeric clipboard pads are selected, show duplicate sorting link:
914 if ($this->clipNumPane()) {
915 $theData[$fCol] .= '<a href="' . htmlspecialchars($this->listURL('', -1) . '&duplicateField=' . $fCol) . '" title="' . $GLOBALS['LANG']->getLL('clip_duplicates', TRUE) . '">' .
916 t3lib_iconWorks::getSpriteIcon('actions-document-duplicates-select') .
920 // If the table can be edited, add link for editing THIS field for all listed records:
921 if (!$GLOBALS['TCA'][$table]['ctrl']['readOnly'] && $permsEdit && $GLOBALS['TCA'][$table]['columns'][$fCol]) {
922 $editIdList = implode(',',$currentIdList);
923 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
924 $params='&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.$fCol.'&disHelp=1';
925 $iTitle = sprintf($GLOBALS['LANG']->getLL('editThisColumn'), rtrim(trim($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel($table, $fCol))), ':'));
926 $theData[$fCol].='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'" title="'.htmlspecialchars($iTitle).'">'.
927 t3lib_iconWorks::getSpriteIcon('actions-document-open') .
931 $theData[$fCol] .= $this->addSortLink($GLOBALS['LANG']->sL(t3lib_BEfunc::getItemLabel($table, $fCol, '<i>[|]</i>')), $fCol, $table);
938 * @hook renderListHeader: Allows to change the contents of columns/cells of the Web>List table headers
940 * @request Bernhard Kraft <krafbt@kraftb.at>
941 * @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.
943 if(is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
944 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
945 $hookObject = t3lib_div::getUserObj($classData);
946 if(!($hookObject instanceof localRecordList_actionsHook)) {
947 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567855);
949 $theData = $hookObject->renderListHeader($table, $currentIdList, $theData, $this);
953 // Create and return header table row:
954 return $this->addelement(1, $icon, $theData, ' class="c-headLine"', '');
958 * Creates a page browser for tables with many records
960 * @param string Distinguish between 'top' and 'bottom' part of the navigation (above or below the records)
961 * @return string Navigation HTML
964 protected function renderListNavigation($renderPart = 'top') {
965 $totalPages = ceil($this->totalItems / $this->iLimit);
970 // Show page selector if not all records fit into one page
971 if ($totalPages > 1) {
972 $first = $previous = $next = $last = $reload = '';
973 $listURL = $this->listURL('', $this->table);
976 $currentPage = floor(($this->firstElementNumber + 1) / $this->iLimit) + 1;
978 // Compile first, previous, next, last and refresh buttons
979 if ($currentPage > 1) {
980 $labelFirst = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:first');
982 $first = '<a href="' . $listURL . '&pointer=0">' .
983 t3lib_iconWorks::getSpriteIcon('actions-view-paging-first', array('title'=> $labelFirst)) .
986 $first = t3lib_iconWorks::getSpriteIcon('actions-view-paging-first-disabled');
989 if (($currentPage - 1) > 0) {
990 $labelPrevious = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:previous');
992 $previous = '<a href="' . $listURL . '&pointer=' . (($currentPage - 2) * $this->iLimit) . '">' .
993 t3lib_iconWorks::getSpriteIcon('actions-view-paging-previous', array('title' => $labelPrevious)) .
996 $previous = t3lib_iconWorks::getSpriteIcon('actions-view-paging-previous-disabled');
999 if (($currentPage + 1) <= $totalPages) {
1000 $labelNext = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:next');
1002 $next = '<a href="' . $listURL . '&pointer=' . (($currentPage) * $this->iLimit) . '">' .
1003 t3lib_iconWorks::getSpriteIcon('actions-view-paging-next', array('title' => $labelNext)) .
1006 $next = t3lib_iconWorks::getSpriteIcon('actions-view-paging-next-disabled');
1009 if ($currentPage != $totalPages) {
1010 $labelLast = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:last');
1012 $last = '<a href="' . $listURL . '&pointer=' . (($totalPages - 1) * $this->iLimit) . '">' .
1013 t3lib_iconWorks::getSpriteIcon('actions-view-paging-last', array('title' => $labelLast)) .
1016 $last = t3lib_iconWorks::getSpriteIcon('actions-view-paging-last-disabled');
1019 $reload = '<a href="#" onclick="document.dblistForm.action=\''
1020 . $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) . '">' .
1021 t3lib_iconWorks::getSpriteIcon('actions-system-refresh') .
1024 if ($renderPart === 'top') {
1025 // Add js to traverse a page select input to a pointer value
1027 <script type="text/JavaScript">
1030 function calculatePointer(page) {
1031 if (page > ' . $totalPages . ') {
1032 page = ' . $totalPages . ';
1039 pointer = (page - 1) * ' . $this->iLimit . ';
1048 $pageNumberInput = '<span>
1049 <input type="text" value="' . $currentPage
1050 . '" 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;" />
1052 $pageIndicator = '<span class="pageIndicator">'
1053 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:pageIndicator'), $pageNumberInput, $totalPages)
1056 if ($this->totalItems > ($this->firstElementNumber + $this->iLimit)) {
1057 $lastElementNumber = $this->firstElementNumber + $this->iLimit;
1059 $lastElementNumber = $this->totalItems;
1061 $rangeIndicator = '<span class="pageIndicator">'
1062 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:rangeIndicator'), $this->firstElementNumber + 1, $lastElementNumber)
1065 $content .= '<div id="typo3-dblist-pagination">'
1066 . $first . $previous
1067 . '<span class="bar"> </span>'
1068 . $rangeIndicator . '<span class="bar"> </span>'
1069 . $pageIndicator . '<span class="bar"> </span>'
1070 . $next . $last . '<span class="bar"> </span>'
1075 $titleColumn = $this->fieldArray[0];
1076 $data[$titleColumn] = $content;
1078 $returnContent = $this->addElement(1, '', $data);
1079 } // end of if pages > 1
1081 return $returnContent;
1089 /*********************************
1091 * Rendering of various elements
1093 *********************************/
1096 * Creates the control panel for a single record in the listing.
1098 * @param string The table
1099 * @param array The record for which to make the control panel.
1100 * @return string HTML table with the control panel (unless disabled)
1102 function makeControl($table,$row) {
1103 if ($this->dontShowClipControlPanels) return '';
1105 $rowUid = $row['uid'];
1106 if (t3lib_extMgm::isLoaded('version') && isset($row['_ORIG_uid'])) {
1107 $rowUid = $row['_ORIG_uid'];
1111 t3lib_div::loadTCA($table);
1114 // If the listed table is 'pages' we have to request the permission settings for each page:
1115 if ($table=='pages') {
1116 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$row['uid']));
1119 // This expresses the edit permissions for this particular element:
1120 $permsEdit = ($table=='pages' && ($localCalcPerms&2)) || ($table!='pages' && ($this->calcPerms&16));
1122 // "Show" link (only pages and tt_content elements)
1123 if ($table=='pages' || $table=='tt_content') {
1124 $params='&edit['.$table.']['.$row['uid'].']=edit';
1125 $cells['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewOnClick(
1126 $table=='tt_content' ? $this->id . '#' . $row['uid'] : $row['uid'],
1128 ) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', TRUE) . '">' .
1129 t3lib_iconWorks::getSpriteIcon('actions-document-view') . '</a>';
1130 } elseif(!$this->table) {
1131 $cells['view'] = $this->spaceIcon;
1134 // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
1136 $params='&edit['.$table.']['.$row['uid'].']=edit';
1137 $cells['edit'] = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) .
1138 '" title="' . $GLOBALS['LANG']->getLL('edit', TRUE) . '">' .
1139 ( $GLOBALS['TCA'][$table]['ctrl']['readOnly'] ? t3lib_iconWorks::getSpriteIcon('actions-document-open-read-only') : t3lib_iconWorks::getSpriteIcon('actions-document-open')) .
1141 } elseif(!$this->table) {
1142 $cells['edit'] = $this->spaceIcon;
1145 // "Move" wizard link for pages/tt_content elements:
1146 if (($table=="tt_content" && $permsEdit) || ($table=='pages')) {
1147 $cells['move'] = '<a href="#" onclick="' .
1149 'return jumpExt(\'' . $this->backPath . 'move_el.php?table=' . $table . '&uid='.$row['uid'] . '\');'
1150 ) .'" title="' . $GLOBALS['LANG']->getLL('move_' . ($table == 'tt_content' ? 'record' : 'page'), TRUE) . '">' .
1151 ($table == 'tt_content' ? t3lib_iconWorks::getSpriteIcon('actions-document-move') : t3lib_iconWorks::getSpriteIcon('actions-page-move')) .
1153 } elseif(!$this->table) {
1154 $cells['move'] = $this->spaceIcon;
1157 // If the extended control panel is enabled OR if we are seeing a single table:
1158 if ($GLOBALS['SOBE']->MOD_SETTINGS['bigControlPanel'] || $this->table) {
1160 // "Info": (All records)
1161 $cells['viewBig'] = '<a href="#" onclick="' . htmlspecialchars(
1162 'top.launchView(\'' . $table . '\', \''.$row['uid'] . '\'); return false;'
1163 ) . '" title="' . $GLOBALS['LANG']->getLL('showInfo', TRUE) . '">'.
1164 t3lib_iconWorks::getSpriteIcon('actions-document-info') .
1167 // If the table is NOT a read-only table, then show these links:
1168 if (!$GLOBALS['TCA'][$table]['ctrl']['readOnly']) {
1170 // "Revert" link (history/undo)
1171 $cells['history'] = '<a href="#" onclick="' . htmlspecialchars(
1172 'return jumpExt(\'' . $this->backPath . 'show_rechis.php?element=' . rawurlencode($table . ':' . $row['uid']) . '\',\'#latest\');') .
1173 '" title="' . $GLOBALS['LANG']->getLL('history', TRUE) . '">'.
1174 t3lib_iconWorks::getSpriteIcon('actions-document-history-open') .
1178 if (t3lib_extMgm::isLoaded('version') && !t3lib_extMgm::isLoaded('workspaces')) {
1179 $vers = t3lib_BEfunc::selectVersionsOfRecord($table, $row['uid'], 'uid', $GLOBALS['BE_USER']->workspace, FALSE, $row);
1180 if (is_array($vers)) { // If table can be versionized.
1181 $versionIcon = 'no-version';
1182 if (count($vers) > 1) {
1183 $versionIcon = count($vers) - 1;
1186 $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) . '">' .
1187 t3lib_iconWorks::getSpriteIcon('status-version-' . $versionIcon) .
1189 } elseif(!$this->table) {
1190 $cells['version'] = $this->spaceIcon;
1194 // "Edit Perms" link:
1195 if ($table == 'pages' && $GLOBALS['BE_USER']->check('modules','web_perm') && t3lib_extMgm::isLoaded('perm')) {
1199 t3lib_extMgm::extRelPath('perm') . 'mod1/index.php' .
1200 '?id=' . $row['uid'] . '&return_id=' . $row['uid'] . '&edit=1'
1202 '" title="' . $GLOBALS['LANG']->getLL('permissions', TRUE) .
1204 t3lib_iconWorks::getSpriteIcon('status-status-locked') .
1206 } elseif(!$this->table && $GLOBALS['BE_USER']->check('modules','web_perm')) {
1207 $cells['perms'] = $this->spaceIcon;
1210 // "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):
1211 if ($GLOBALS['TCA'][$table]['ctrl']['sortby'] || $GLOBALS['TCA'][$table]['ctrl']['useColumnsForDefaultValues']) {
1213 ($table!='pages' && ($this->calcPerms&16)) || // For NON-pages, must have permission to edit content on this parent page
1214 ($table=='pages' && ($this->calcPerms&8)) // For pages, must have permission to create new pages here.
1216 if ($this->showNewRecLink($table)) {
1217 $params='&edit['.$table.']['.(-($row['_MOVE_PLH']?$row['_MOVE_PLH_uid']:$row['uid'])).']=new';
1218 $cells['new'] = '<a href="#" onclick="' . htmlspecialchars(
1219 t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) .
1220 '" title="' . $GLOBALS['LANG']->getLL('new' . ($table == 'pages '? 'Page' : 'Record'), TRUE) . '">' .
1221 ($table == 'pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) .
1225 } elseif(!$this->table) {
1226 $cells['new'] = $this->spaceIcon;
1230 if ($permsEdit && $GLOBALS['TCA'][$table]['ctrl']['sortby'] && !$this->sortField && !$this->searchLevels) {
1231 if (isset($this->currentTable['prev'][$row['uid']])) { // Up
1232 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prev'][$row['uid']];
1233 $cells['moveUp'] = '<a href="#" onclick="' . htmlspecialchars(
1234 'return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');'
1235 ) .'" title="'.$GLOBALS['LANG']->getLL('moveUp', TRUE) . '">' .
1236 t3lib_iconWorks::getSpriteIcon('actions-move-up') .
1239 $cells['moveUp'] = $this->spaceIcon;
1241 if ($this->currentTable['next'][$row['uid']]) { // Down
1242 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['next'][$row['uid']];
1243 $cells['moveDown']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$GLOBALS['SOBE']->doc->issueCommand($params,-1).'\');').'" title="'.$GLOBALS['LANG']->getLL('moveDown', TRUE) . '">' .
1244 t3lib_iconWorks::getSpriteIcon('actions-move-down') .
1247 $cells['moveDown'] = $this->spaceIcon;
1249 } elseif(!$this->table) {
1250 $cells['moveUp'] = $this->spaceIcon;
1251 $cells['moveDown'] = $this->spaceIcon;
1254 // "Hide/Unhide" links:
1255 $hiddenField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
1256 if ($permsEdit && $hiddenField && $GLOBALS['TCA'][$table]['columns'][$hiddenField] && (!$GLOBALS['TCA'][$table]['columns'][$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $hiddenField))) {
1257 if ($row[$hiddenField]) {
1258 $params = '&data[' . $table . '][' . $rowUid . '][' . $hiddenField . ']=0';
1259 $cells['hide']='<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '" title="'.$GLOBALS['LANG']->getLL('unHide' . ($table == 'pages' ? 'Page' : ''), TRUE) . '">' .
1260 t3lib_iconWorks::getSpriteIcon('actions-edit-unhide') .
1263 $params = '&data[' . $table . '][' . $rowUid . '][' . $hiddenField . ']=1';
1264 $cells['hide']='<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '" title="' . $GLOBALS['LANG']->getLL('hide' . ($table == 'pages' ? 'Page' : ''), TRUE) . '">' .
1265 t3lib_iconWorks::getSpriteIcon('actions-edit-hide') .
1268 } elseif(!$this->table) {
1269 $cells['hide'] = $this->spaceIcon;
1273 if (($table=='pages' && ($localCalcPerms&4)) || ($table!='pages' && ($this->calcPerms&16))) {
1274 $titleOrig = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
1275 $title = t3lib_div::slashJS(t3lib_div::fixed_lgd_cs($titleOrig, $this->fixedL), 1);
1276 $params = '&cmd['.$table.']['.$row['uid'].'][delete]=1';
1278 $refCountMsg = t3lib_BEfunc::referenceCount(
1281 ' ' . $GLOBALS['LANG']->sL(
1282 'LLL:EXT:lang/locallang_core.xml:labels.referencesToRecord'
1284 $this->getReferenceCount($table, $row['uid'])
1286 t3lib_BEfunc::translationCount($table, $row['uid'], ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.translationsOfRecord'));
1287 $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) . '">' .
1288 t3lib_iconWorks::getSpriteIcon('actions-edit-delete') .
1290 } elseif(!$this->table) {
1291 $cells['delete'] = $this->spaceIcon;
1294 // "Levels" links: Moving pages into new levels...
1295 if ($permsEdit && $table=='pages' && !$this->searchLevels) {
1297 // Up (Paste as the page right after the current parent page)
1298 if ($this->calcPerms&8) {
1299 $params='&cmd['.$table.']['.$row['uid'].'][move]='.-$this->id;
1300 $cells['moveLeft'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '" title="' . $GLOBALS['LANG']->getLL('prevLevel', TRUE) . '">' .
1301 t3lib_iconWorks::getSpriteIcon('actions-move-left') .
1304 // Down (Paste as subpage to the page right above)
1305 if ($this->currentTable['prevUid'][$row['uid']]) {
1306 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$this->currentTable['prevUid'][$row['uid']]));
1307 if ($localCalcPerms&8) {
1308 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prevUid'][$row['uid']];
1309 $cells['moveRight'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '" title="' . $GLOBALS['LANG']->getLL('nextLevel', TRUE) . '">' .
1310 t3lib_iconWorks::getSpriteIcon('actions-move-right') .
1313 $cells['moveRight'] = $this->spaceIcon;
1316 $cells['moveRight'] = $this->spaceIcon;
1318 } elseif(!$this->table) {
1319 $cells['moveLeft'] = $this->spaceIcon;
1320 $cells['moveRight'] = $this->spaceIcon;
1327 * @hook recStatInfoHooks: Allows to insert HTML before record icons on various places
1329 * @request Kasper Skårhøj <kasper2007@typo3.com>
1331 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) {
1333 $_params = array($table,$row['uid']);
1334 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) {
1335 $stat.=t3lib_div::callUserFunction($_funcRef,$_params,$this);
1337 $cells['stat'] = $stat;
1340 * @hook makeControl: Allows to change control icons of records in list-module
1342 * @request Bernhard Kraft <krafbt@kraftb.at>
1343 * @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.
1345 if(is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1346 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1347 $hookObject = t3lib_div::getUserObj($classData);
1348 if(!($hookObject instanceof localRecordList_actionsHook)) {
1349 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567840);
1351 $cells = $hookObject->makeControl($table, $row, $cells, $this);
1355 // Compile items into a DIV-element:
1357 <!-- CONTROL PANEL: '.$table.':'.$row['uid'].' -->
1358 <div class="typo3-DBctrl">'.implode('',$cells).'</div>';
1362 * Creates the clipboard panel for a single record in the listing.
1364 * @param string The table
1365 * @param array The record for which to make the clipboard panel.
1366 * @return string HTML table with the clipboard panel (unless disabled)
1368 function makeClip($table,$row) {
1369 // Return blank, if disabled:
1370 if ($this->dontShowClipControlPanels) return '';
1373 $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon;
1374 //enables to hide the copy, cut and paste icons for localized records - doesn't make much sense to perform these options for them
1375 $isL10nOverlay = $this->localizationView && $table != 'pages_language_overlay' && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0;
1376 // Return blank, if disabled:
1377 // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel:
1378 if ($this->clipObj->current=='normal') { // For the "Normal" pad:
1380 // Show copy/cut icons:
1381 $isSel = (string)$this->clipObj->isSelected($table,$row['uid']);
1382 $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) . '">' .
1383 ((!$isSel=='copy') ? t3lib_iconWorks::getSpriteIcon('actions-edit-copy') : t3lib_iconWorks::getSpriteIcon('actions-edit-copy-release')) .
1385 $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) . '">' .
1386 ((!$isSel=='cut') ? t3lib_iconWorks::getSpriteIcon('actions-edit-cut') : t3lib_iconWorks::getSpriteIcon('actions-edit-cut-release')) .
1389 } else { // For the numeric clipboard pads (showing checkboxes where one can select elements on/off)
1391 // Setting name of the element in ->CBnames array:
1392 $n=$table.'|'.$row['uid'];
1393 $this->CBnames[]=$n;
1395 // Check if the current element is selected and if so, prepare to set the checkbox as selected:
1396 $checked = ($this->clipObj->isSelected($table,$row['uid'])?' checked="checked"':'');
1398 // If the "duplicateField" value is set then select all elements which are duplicates...
1399 if ($this->duplicateField && isset($row[$this->duplicateField])) {
1401 if (in_array($row[$this->duplicateField], $this->duplicateStack)) {
1402 $checked=' checked="checked"';
1404 $this->duplicateStack[] = $row[$this->duplicateField];
1407 // Adding the checkbox to the panel:
1408 $cells['select'] = $isL10nOverlay ? $this->spaceIcon : '<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />';
1411 // Now, looking for selected elements from the current table:
1412 $elFromTable = $this->clipObj->elFromTable($table);
1413 if (count($elFromTable) && $GLOBALS['TCA'][$table]['ctrl']['sortby']){
1414 // IF elements are found and they can be individually ordered, then add a "paste after" icon:
1415 $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) . '">' .
1416 t3lib_iconWorks::getSpriteIcon('actions-document-paste-after') .
1420 // Now, looking for elements in general:
1421 $elFromTable = $this->clipObj->elFromTable('');
1422 if ($table=='pages' && count($elFromTable)) {
1423 $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) . '">' .
1424 t3lib_iconWorks::getSpriteIcon('actions-document-paste-into') .
1429 * @hook makeClip: Allows to change clip-icons of records in list-module
1431 * @request Bernhard Kraft <krafbt@kraftb.at>
1432 * @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.
1434 if(is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1435 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1436 $hookObject = t3lib_div::getUserObj($classData);
1437 if(!($hookObject instanceof localRecordList_actionsHook)) {
1438 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567845);
1440 $cells = $hookObject->makeClip($table, $row, $cells, $this);
1444 // Compile items into a DIV-element:
1445 return ' <!-- CLIPBOARD PANEL: '.$table.':'.$row['uid'].' -->
1446 <div class="typo3-clipCtrl">'.implode('',$cells).'</div>';
1450 * Creates the HTML for a reference count for the record with the UID $uid
1451 * in the table $tableName.
1453 * @param string $tableName
1454 * table name of the referenced record, must not be empty
1455 * @param integer $uid
1456 * UID of the referenced record, must be > 0
1458 * @return string HTML of reference a link, will be empty if there are no
1459 * references to the corresponding record
1461 protected function createReferenceHtml($tableName, $uid) {
1462 $referenceCount = $this->getReferenceCount($tableName, $uid);
1463 if ($referenceCount == 0) {
1467 $queryResult = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1468 'tablename, recuid, field',
1470 'ref_table = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr(
1471 $tableName, 'sys_refindex'
1473 ' AND ref_uid = ' . $uid .
1480 $referenceTitles = array();
1482 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($queryResult)) {
1483 $referenceTitles[] = $row['tablename'] . ':' . $row['recuid'] .
1484 ':' . $row['field'];
1485 if (strlen(implode(' / ', $referenceTitles)) >= 100) {
1489 $GLOBALS['TYPO3_DB']->sql_free_result($queryResult);
1491 return '<a href="#" ' .
1492 'onclick="' . htmlspecialchars(
1493 'top.launchView(\'' . $tableName . '\', \'' . $uid .
1494 '\'); return false;'
1496 'title="' . htmlspecialchars(
1497 t3lib_div::fixed_lgd_cs(implode(' / ', $referenceTitles), 100)
1498 ) . '">' . $referenceCount . '</a>';
1502 * Creates the localization panel
1504 * @param string The table
1505 * @param array The record for which to make the localization panel.
1506 * @return array Array with key 0/1 with content for column 1 and 2
1508 function makeLocalizationPanel($table,$row) {
1514 $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList);
1515 $this->translations = $translations['translations'];
1517 // Language title and icon:
1518 $out[0] = $this->languageFlag($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]);
1520 if (is_array($translations)) {
1522 // Traverse page translations and add icon for each language that does NOT yet exist:
1524 foreach($this->pageOverlays as $lUid_OnPage => $lsysRec) {
1525 if (!isset($translations['translations'][$lUid_OnPage]) && $GLOBALS['BE_USER']->checkLanguageAccess($lUid_OnPage)) {
1526 $url = substr($this->listURL(), strlen($this->backPath));
1527 $href = $GLOBALS['SOBE']->doc->issueCommand(
1528 '&cmd[' . $table . '][' . $row['uid'] . '][localize]=' . $lUid_OnPage,
1529 $url . '&justLocalized=' . rawurlencode($table . ':' . $row['uid'] . ':' . $lUid_OnPage)
1531 $language = t3lib_BEfunc::getRecord('sys_language', $lUid_OnPage, 'title');
1532 if ($this->languageIconTitles[$lUid_OnPage]['flagIcon']) {
1533 $lC = t3lib_iconWorks::getSpriteIcon($this->languageIconTitles[$lUid_OnPage]['flagIcon']);
1535 $lC = $this->languageIconTitles[$lUid_OnPage]['title'];
1537 $lC = '<a href="' . htmlspecialchars($href) . '" title="' . htmlspecialchars($language['title']) . '">' . $lC . '</a> ';
1543 if ($lNew) $out[1].= $lNew;
1544 } elseif ($row['l18n_parent']) {
1545 $out[0] = ' '.$out[0];
1553 * Create the selector box for selecting fields to display from a table:
1555 * @param string Table name
1556 * @param boolean If TRUE, form-fields will be wrapped around the table.
1557 * @return string HTML table with the selector box (name: displayFields['.$table.'][])
1559 function fieldSelectBox($table,$formFields=1) {
1562 t3lib_div::loadTCA($table);
1563 $formElements=array('','');
1565 $formElements=array('<form action="'.htmlspecialchars($this->listURL()).'" method="post">','</form>');
1568 // Load already selected fields, if any:
1569 $setFields=is_array($this->setFields[$table]) ? $this->setFields[$table] : array();
1571 // Request fields from table:
1572 $fields = $this->makeFieldList($table, FALSE, TRUE);
1574 // Add pseudo "control" fields
1577 $fields[]='_LOCALIZATION_';
1578 $fields[]='_CONTROL_';
1579 $fields[]='_CLIPBOARD_';
1581 // Create an option for each field:
1583 $opt[] = '<option value=""></option>';
1584 foreach($fields as $fN) {
1586 $fL = (is_array($GLOBALS['TCA'][$table]['columns'][$fN])
1587 ? rtrim($GLOBALS['LANG']->sL($GLOBALS['TCA'][$table]['columns'][$fN]['label']), ':')
1590 <option value="'.$fN.'"'.(in_array($fN,$setFields)?' selected="selected"':'').'>'.htmlspecialchars($fL).'</option>';
1593 // Compile the options into a multiple selector box:
1595 <select size="'.t3lib_utility_Math::forceIntegerInRange(count($fields)+1,3,20).'" multiple="multiple" name="displayFields['.$table.'][]">'.implode('',$opt).'
1599 // Table with the field selector::
1600 $content = $formElements[0] . '
1603 Field selector for extended table view:
1605 <table border="0" cellpadding="0" cellspacing="0" id="typo3-dblist-fieldSelect">
1608 <td><input type="submit" name="search" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.setFields', 1) . '" /></td>
1611 ' . $formElements[1];
1613 return '<div class="db_list-fieldSelect">' . $content . '</div>';
1626 /*********************************
1630 *********************************/
1633 * Creates a link around $string. The link contains an onclick action which submits the script with some clipboard action.
1634 * Currently, this is used for setting elements / delete elements.
1636 * @param string The HTML content to link (image/text)
1637 * @param string Table name
1638 * @param string Clipboard command (eg. "setCB" or "delete")
1639 * @param string Warning text, if any ("delete" uses this for confirmation)
1640 * @return string <a> tag wrapped link.
1642 function linkClipboardHeaderIcon($string,$table,$cmd,$warning='') {
1643 $onClickEvent = 'document.dblistForm.cmd.value=\''.$cmd.'\';document.dblistForm.cmd_table.value=\''.$table.'\';document.dblistForm.submit();';
1644 if ($warning) $onClickEvent = 'if (confirm('.$GLOBALS['LANG']->JScharCode($warning).')){'.$onClickEvent.'}';
1645 return '<a href="#" onclick="'.htmlspecialchars($onClickEvent.'return false;').'">'.$string.'</a>';
1649 * Returns TRUE if a numeric clipboard pad is selected/active
1653 function clipNumPane() {
1654 return in_Array('_CLIPBOARD_',$this->fieldArray) && $this->clipObj->current!='normal';
1658 * Creates a sort-by link on the input string ($code).
1659 * It will automatically detect if sorting should be ascending or descending depending on $this->sortRev.
1660 * Also some fields will not be possible to sort (including if single-table-view is disabled).
1662 * @param string The string to link (text)
1663 * @param string The fieldname represented by the title ($code)
1664 * @param string Table name
1665 * @return string Linked $code variable
1667 function addSortLink($code,$field,$table) {
1669 // Certain circumstances just return string right away (no links):
1670 if ($field=='_CONTROL_' || $field=='_LOCALIZATION_' || $field=='_CLIPBOARD_' || $field=='_REF_' || $this->disableSingleTableView) return $code;
1672 // If "_PATH_" (showing record path) is selected, force sorting by pid field (will at least group the records!)
1673 if ($field=='_PATH_') $field=pid;
1675 // Create the sort link:
1676 $sortUrl = $this->listURL('', -1, 'sortField,sortRev,table,firstElementNumber') . '&table=' . $table . '&sortField=' . $field . '&sortRev=' . ($this->sortRev || ($this->sortField != $field) ? 0 : 1);
1677 $sortArrow = ($this->sortField==$field?'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/red'.($this->sortRev?'up':'down').'.gif','width="7" height="4"').' alt="" />':'');
1679 // Return linked field:
1680 return '<a href="'.htmlspecialchars($sortUrl).'">'.$code.
1686 * Returns the path for a certain pid
1687 * The result is cached internally for the session, thus you can call this function as much as you like without performance problems.
1689 * @param integer The page id for which to get the path
1690 * @return string The path.
1692 function recPath($pid) {
1693 if (!isset($this->recPath_cache[$pid])) {
1694 $this->recPath_cache[$pid] = t3lib_BEfunc::getRecordPath($pid,$this->perms_clause,20);
1696 return $this->recPath_cache[$pid];
1700 * Returns TRUE if a link for creating new records should be displayed for $table
1702 * @param string Table name
1703 * @return boolean Returns TRUE if a link for creating new records should be displayed for $table
1704 * @see SC_db_new::showNewRecLink
1706 function showNewRecLink($table) {
1707 // No deny/allow tables are set:
1708 if (!count($this->allowedNewTables) && !count($this->deniedNewTables)) {
1710 // If table is not denied (which takes precedence over allowed tables):
1711 } elseif (!in_array($table, $this->deniedNewTables) && (!count($this->allowedNewTables) || in_array($table, $this->allowedNewTables))) {
1713 // If table is denied or allowed tables are set, but table is not part of:
1720 * 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.
1721 * Uses REQUEST_URI as value.
1725 function makeReturnUrl() {
1726 return '&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
1739 /************************************
1741 * CSV related functions
1743 ************************************/
1746 * Initializes internal csvLines array with the header of field names
1750 protected function initCSV() {
1751 $this->addHeaderRowToCSV();
1755 * Add header line with field names as CSV line
1759 protected function addHeaderRowToCSV() {
1760 // Add header row, control fields will be reduced inside addToCSV()
1761 $this->addToCSV(array_combine($this->fieldArray, $this->fieldArray));
1765 * Adds selected columns of one table row as CSV line.
1767 * @param array Record array, from which the values of fields found in $this->fieldArray will be listed in the CSV output.
1770 protected function addToCSV(array $row = array()) {
1771 $rowReducedByControlFields = self::removeControlFieldsFromFieldRow($row);
1772 $rowReducedToSelectedColumns = array_intersect_key($rowReducedByControlFields, array_flip($this->fieldArray));
1773 $this->setCsvRow($rowReducedToSelectedColumns);
1777 * Remove control fields from row for CSV export
1779 * @param array fieldNames => fieldValues
1780 * @return array Input array reduces by control fields
1782 protected static function removeControlFieldsFromFieldRow(array $row = array()) {
1783 // Possible control fields in a list row
1784 $controlFields = array(
1794 return array_diff_key($row, array_flip($controlFields));
1799 * Adds input row of values to the internal csvLines array as a CSV formatted line
1801 * @param array Array with values to be listed.
1804 function setCsvRow($csvRow) {
1805 $this->csvLines[] = t3lib_div::csvValues($csvRow);
1809 * Compiles the internal csvLines array to a csv-string and outputs it to the browser.
1810 * This function exits!
1812 * @param string Filename prefix:
1813 * @return void EXITS php execusion!
1815 function outputCSV($prefix) {
1817 // Setting filename:
1818 $filename=$prefix.'_'.date('dmy-Hi').'.csv';
1820 // Creating output header:
1821 $mimeType = 'application/octet-stream';
1822 Header('Content-Type: '.$mimeType);
1823 Header('Content-Disposition: attachment; filename='.$filename);
1825 // Printing the content of the CSV lines:
1826 echo implode(chr(13).chr(10),$this->csvLines);
1835 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc'])) {
1836 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']);