2 /*************************************************************
5 * (c) 1999-2009 Kasper Skaarhoj (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)
32 * Revised for TYPO3 3.6 December/2003 by Kasper Skaarhoj
35 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
38 * [CLASS/FUNCTION INDEX of SCRIPT]
42 * 91: class localRecordList extends recordList
43 * 123: function writeTop($row)
44 * 304: function getTable($table,$id,$rowlist)
45 * 559: function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0)
46 * 648: function renderListHeader($table,$currentIdList)
48 * SECTION: Rendering of various elements
49 * 796: function makeControl($table,$row)
50 * 986: function makeClip($table,$row)
51 * 1057: function makeRef($table,$uid)
52 * 1086: function makeLocalizationPanel($table,$row)
53 * 1148: function fieldSelectBox($table,$formFields=1)
55 * SECTION: Helper functions
56 * 1231: function linkClipboardHeaderIcon($string,$table,$cmd,$warning='')
57 * 1242: function clipNumPane()
58 * 1256: function addSortLink($code,$field,$table)
59 * 1281: function recPath($pid)
60 * 1294: function showNewRecLink($table)
61 * 1304: function makeReturnUrl()
63 * SECTION: CSV related functions
64 * 1329: function initCSV()
65 * 1352: function addToCSV($row,$table)
66 * 1376: function setCsvRow($csvRow)
67 * 1387: function outputCSV($prefix)
70 * (This index is automatically created/updated by the extension "extdeveval")
84 * Class for rendering of Web>List module
86 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
90 class localRecordList extends recordList {
93 var $alternateBgColors=FALSE; // If true, table rows in the list will alternate in background colors (and have background colors at all!)
94 var $allowedNewTables=array(); // Used to indicate which tables (values in the array) that can have a create-new-record link. If the array is empty, all tables are allowed.
95 var $deniedNewTables=array(); // Used to indicate which tables (values in the array) that cannot have a create-new-record link. If the array is empty, all tables are allowed.
96 var $newWizards=FALSE; // If true, the control panel will contain links to the create-new wizards for pages and tt_content elements (normally, the link goes to just creating a new element without the wizards!).
98 var $dontShowClipControlPanels=FALSE; // If true, will disable the rendering of clipboard + control panels.
99 var $showClipboard=FALSE; // If true, will show the clipboard in the field list.
100 var $noControlPanels = FALSE; // If true, will DISABLE all control panels in lists. (Takes precedence)
101 var $clickMenuEnabled = TRUE; // If true, clickmenus will be rendered
103 var $totalRowCount; // count of record rows in view
105 var $spaceIcon; // space icon used for alignment
108 var $pageRow=array(); // Set to the page record (see writeTop())
110 var $csvLines=array(); // Used to accumulate CSV lines in for CSV export.
111 var $csvOutput=FALSE; // If set, the listing is returned as CSV instead.
116 * @var t3lib_clipboard
119 var $CBnames=array(); // Tracking names of elements (for clipboard use)
120 var $duplicateStack=array(); // Used to track which elements has duplicates and how many
123 * references of the current record
127 * @deprecated since 4.4: Use getReferenceCount instead
132 * [$tablename][$uid] = number of references to this record
136 protected $referenceCount = array();
138 var $translations; // Translations of the current record
139 var $selFieldList; // select fields for the query which fetches the translations of the current record
141 public function __construct() {
142 parent::__construct();
146 * Create the panel of buttons for submitting the form or otherwise perform operations.
148 * @return array all available buttons as an assoc. array
150 public function getButtons() {
170 // Get users permissions for this page record:
171 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms($this->pageRow);
174 if (!strlen($this->id)) {
175 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_noId', $GLOBALS['BACK_PATH'], '', TRUE);
176 } elseif(!$this->id) {
177 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_root', $GLOBALS['BACK_PATH'], '', TRUE);
179 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module', $GLOBALS['BACK_PATH'], '', TRUE);
182 if (isset($this->id)) {
183 // View Exclude doktypes 254,255 Configuration: mod.web_list.noViewWithDokTypes = 254,255
184 if (isset($GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'])) {
185 $noViewDokTypes = t3lib_div::trimExplode(',', $GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'], true);
187 //default exclusion: doktype 254, 255
188 $noViewDokTypes = array('254', '255');
191 if (!in_array($this->pageRow['doktype'], $noViewDokTypes)) {
192 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewOnClick($this->id, $this->backPath, t3lib_BEfunc::BEgetRootLine($this->id))) . '">' .
193 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/zoom.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', 1) . '" alt="" />' .
198 if (!$GLOBALS['SOBE']->modTSconfig['properties']['noCreateRecordsLink']) {
199 $buttons['new_record'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'db_new.php?id=' . $this->id . '\');') . '">' .
200 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/new_el.gif') . ' title="' . $LANG->getLL('newRecordGeneral', 1) . '" alt="" />' .
204 // If edit permissions are set (see class.t3lib_userauthgroup.php)
205 if ($localCalcPerms&2 && !empty($this->id)) {
208 $params = '&edit[pages][' . $this->pageRow['uid'] . ']=edit';
209 $buttons['edit'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) . '">' .
210 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/edit2.gif') . ' title="' . $LANG->getLL('editPage', 1) . '" alt="" />' .
213 if ($this->pageRow['hidden']) {
214 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=0';
215 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '">' .
216 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/button_unhide.gif') . ' title="' . $LANG->getLL('unHidePage', 1) . '" alt="" />' .
220 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=1';
221 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '">'.
222 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/button_hide.gif') . ' title="' . $LANG->getLL('hidePage', 1) . '" alt="" />' .
227 $buttons['move'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'move_el.php?table=pages&uid=' . $this->pageRow['uid'] . '\');') . '">' .
228 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/move_' . ($this->table == 'tt_content' ? 'record' : 'page') . '.gif') . ' title="' . $LANG->getLL('move_page', 1) . '" alt="" />' .
232 $buttons['level_up'] = '<a href="' . htmlspecialchars($this->listURL($this->pageRow['pid'])) . '" onclick="setHighlight(' . $this->pageRow['pid'] . ')">' .
233 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/i/pages_up.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.upOneLevel', 1) . '" alt="" />' .
240 if (($localCalcPerms&8) || ($localCalcPerms&16)) {
241 $elFromTable = $this->clipObj->elFromTable('');
242 if (count($elFromTable)) {
243 $buttons['paste'] = '<a href="' . htmlspecialchars($this->clipObj->pasteUrl('', $this->id)) . '" onclick="' . htmlspecialchars('return ' . $this->clipObj->confirmMsg('pages', $this->pageRow, 'into', $elFromTable)) . '">' .
244 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clip_pasteafter.gif') . ' title="' . $LANG->getLL('clip_paste', 1) . '" alt="" />' .
250 $buttons['cache'] = '<a href="' . htmlspecialchars($this->listURL() . '&clear_cache=1') . '">' .
251 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clear_cache.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.clear_cache', 1) . '" alt="" />' .
257 $buttons['csv'] = '<a href="' . htmlspecialchars($this->listURL() . '&csv=1') . '">' .
258 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/csv.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.csv', 1) . '" alt="" />' .
262 if (t3lib_extMgm::isLoaded('impexp')) {
263 $url = $this->backPath . t3lib_extMgm::extRelPath('impexp') . 'app/index.php?tx_impexp[action]=export';
264 $buttons['export'] = '<a href="' . htmlspecialchars($url . '&tx_impexp[list][]=' . rawurlencode($this->table . ':' . $this->id)) . '">' . '<img' . t3lib_iconWorks::skinImg($this->backPath, t3lib_extMgm::extRelPath('impexp') . 'export.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:rm.export', 1) . '" alt="" />' .
271 $buttons['reload'] = '<a href="' . htmlspecialchars($this->listURL()) . '">' .
272 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/refresh_n.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.reload', 1) . '" alt="" />' .
276 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
277 $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');
281 if ($this->returnUrl) {
282 $buttons['back'] = '<a href="' . htmlspecialchars(t3lib_div::linkThisUrl($this->returnUrl, array('id' => $this->id))) . '" class="typo3-goBack">' .
283 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/goback.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.goBack', 1) . '" alt="" />' .
292 * Creates the listing of records from a single table
294 * @param string Table name
295 * @param integer Page id
296 * @param string List of fields to show in the listing. Pseudo fields will be added including the record header.
297 * @return string HTML table with the listing for the record.
299 function getTable($table,$id,$rowlist) {
300 global $TCA, $TYPO3_CONF_VARS;
302 // Loading all TCA details for this table:
303 t3lib_div::loadTCA($table);
307 $titleCol = $TCA[$table]['ctrl']['label'];
308 $thumbsCol = $TCA[$table]['ctrl']['thumbnail'];
309 $l10nEnabled = $TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField'] && !$TCA[$table]['ctrl']['transOrigPointerTable'];
310 $tableCollapsed = (!$this->tablesCollapsed[$table]) ? false : true;
312 // prepare space icon
313 $iconWidth = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeWidth'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeWidth'] : 12;
314 $iconHeight = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeHeight'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeHeight'] : 12;
315 $this->spaceIcon = '<img src="' . $this->backPath . 'clear.gif" width="' . $iconWidth . '" height="' . $iconHeight . '" title="" alt="" />';
317 // Cleaning rowlist for duplicates and place the $titleCol as the first column always!
318 $this->fieldArray=array();
320 $this->fieldArray[] = $titleCol; // Add title column
322 if (!t3lib_div::inList($rowlist,'_CONTROL_')) {
323 $this->fieldArray[] = '_CONTROL_';
324 $this->fieldArray[] = '_AFTERCONTROL_';
327 if ($this->showClipboard) {
328 $this->fieldArray[] = '_CLIPBOARD_';
331 if (!$this->dontShowClipControlPanels) {
332 $this->fieldArray[]='_REF_';
333 $this->fieldArray[]='_AFTERREF_';
336 if ($this->searchLevels) {
337 $this->fieldArray[]='_PATH_';
340 if ($this->localizationView && $l10nEnabled) {
341 $this->fieldArray[] = '_LOCALIZATION_';
342 $this->fieldArray[] = '_LOCALIZATION_b';
344 '.$TCA[$table]['ctrl']['languageField'].'<=0
346 '.$TCA[$table]['ctrl']['transOrigPointerField'].' = 0
350 $this->fieldArray=array_unique(array_merge($this->fieldArray,t3lib_div::trimExplode(',',$rowlist,1)));
351 if ($this->noControlPanels) {
352 $tempArray = array_flip($this->fieldArray);
353 unset($tempArray['_CONTROL_']);
354 unset($tempArray['_CLIPBOARD_']);
355 $this->fieldArray = array_keys($tempArray);
358 // Creating the list of fields to include in the SQL query:
359 $selectFields = $this->fieldArray;
360 $selectFields[] = 'uid';
361 $selectFields[] = 'pid';
362 if ($thumbsCol) $selectFields[] = $thumbsCol; // adding column for thumbnails
363 if ($table=='pages') {
364 if (t3lib_extMgm::isLoaded('cms')) {
365 $selectFields[] = 'module';
366 $selectFields[] = 'extendToSubpages';
367 $selectFields[] = 'nav_hide';
369 $selectFields[] = 'doktype';
371 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) {
372 $selectFields = array_merge($selectFields,$TCA[$table]['ctrl']['enablecolumns']);
374 if ($TCA[$table]['ctrl']['type']) {
375 $selectFields[] = $TCA[$table]['ctrl']['type'];
377 if ($TCA[$table]['ctrl']['typeicon_column']) {
378 $selectFields[] = $TCA[$table]['ctrl']['typeicon_column'];
380 if ($TCA[$table]['ctrl']['versioningWS']) {
381 $selectFields[] = 't3ver_id';
382 $selectFields[] = 't3ver_state';
383 $selectFields[] = 't3ver_wsid';
384 $selectFields[] = 't3ver_swapmode'; // Filtered out when pages in makeFieldList()
387 $selectFields[] = $TCA[$table]['ctrl']['languageField'];
388 $selectFields[] = $TCA[$table]['ctrl']['transOrigPointerField'];
390 if ($TCA[$table]['ctrl']['label_alt']) {
391 $selectFields = array_merge($selectFields,t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['label_alt'],1));
393 $selectFields = array_unique($selectFields); // Unique list!
394 $selectFields = array_intersect($selectFields,$this->makeFieldList($table,1)); // Making sure that the fields in the field-list ARE in the field-list from TCA!
395 $selFieldList = implode(',',$selectFields); // implode it into a list of fields for the SQL-statement.
396 $this->selFieldList = $selFieldList;
399 * @hook DB-List getTable
401 * @request Malte Jansen <mail@maltejansen.de>
403 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) {
404 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) {
405 $hookObject = t3lib_div::getUserObj($classData);
407 if(!($hookObject instanceof t3lib_localRecordListGetTableHook)) {
408 throw new UnexpectedValueException('$hookObject must implement interface t3lib_localRecordListGetTableHook', 1195114460);
411 $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this);
415 // Create the SQL query for selecting the elements in the listing:
416 if ($this->csvOutput) { // do not do paging when outputting as CSV
420 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
421 // Get the two previous rows for sorting if displaying page > 1
422 $this->firstElementNumber = $this->firstElementNumber - 2;
423 $this->iLimit = $this->iLimit + 2;
424 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc)
425 $this->firstElementNumber = $this->firstElementNumber + 2;
426 $this->iLimit = $this->iLimit - 2;
428 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc)
431 $this->setTotalItems($queryParts); // Finding the total amount of records on the page (API function from class.db_list.inc)
436 $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table;
438 // If the count query returned any number of records, we perform the real query, selecting records.
439 if ($this->totalItems) {
440 // Fetch records only if not in single table mode or if in multi table mode and not collapsed
441 if ($listOnlyInSingleTableMode || (!$this->table && $tableCollapsed)) {
442 $dbCount = $this->totalItems;
444 // set the showLimit to the number of records when outputting as CSV
445 if ($this->csvOutput) {
446 $this->showLimit = $this->totalItems;
447 $this->iLimit = $this->totalItems;
449 $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
450 $dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result);
454 // If any records was selected, render the list:
457 // Half line is drawn between tables:
458 if (!$listOnlyInSingleTableMode) {
460 if (!$this->table && !$rowlist) {
461 $theData[$titleCol] = '<img src="clear.gif" width="'.($GLOBALS['SOBE']->MOD_SETTINGS['bigControlPanel']?'230':'350').'" height="1" alt="" />';
462 if (in_array('_CONTROL_',$this->fieldArray)) $theData['_CONTROL_']='';
463 if (in_array('_CLIPBOARD_',$this->fieldArray)) $theData['_CLIPBOARD_']='';
465 $out.=$this->addelement(0,'',$theData,'class="c-table-row-spacer"',$this->leftMargin);
468 // Header line is drawn
470 if ($this->disableSingleTableView) {
471 $theData[$titleCol] = '<span class="c-table">'.$GLOBALS['LANG']->sL($TCA[$table]['ctrl']['title'],1).'</span> ('.$this->totalItems.')';
473 $theData[$titleCol] = $this->linkWrapTable($table,'<span class="c-table">'.$GLOBALS['LANG']->sL($TCA[$table]['ctrl']['title'],1).'</span> ('.$this->totalItems.') <img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/'.($this->table?'minus':'plus').'bullet_list.gif','width="18" height="12"').' hspace="10" class="absmiddle" title="'.$GLOBALS['LANG']->getLL(!$this->table?'expandView':'contractView',1).'" alt="" />');
477 $theData[$titleCol].= t3lib_BEfunc::cshItem($table,'',$this->backPath,'',FALSE,'margin-bottom:0px; white-space: normal;');
479 if ($listOnlyInSingleTableMode) {
482 <td class="c-headLineTable" style="width:95%;">'.$theData[$titleCol].'</td>
485 if ($GLOBALS['BE_USER']->uc["edit_showFieldHelp"]) {
486 $GLOBALS['LANG']->loadSingleTableDescription($table);
487 if (isset($GLOBALS['TCA_DESCR'][$table]['columns'][''])) {
488 $onClick = 'vHWin=window.open(\'view_help.php?tfID='.$table.'.\',\'viewFieldHelp\',\'height=400,width=600,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;';
491 <td class="c-tableDescription">'.t3lib_BEfunc::helpTextIcon($table,'',$this->backPath,TRUE).$GLOBALS['TCA_DESCR'][$table]['columns']['']['description'].'</td>
496 // Render collapse button if in multi table mode
499 $collapseIcon = '<a href="' . htmlspecialchars($this->listURL() . '&collapse[' . $table . ']=' . ($tableCollapsed ? '0' : '1')) . '"><img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/arrow' . ($tableCollapsed ? 'right' : 'down') . '.png') . ' class="collapseIcon" alt="" title="' . ($tableCollapsed ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.expandTable',1) : $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.collapseTable',1)) . '" /></a>';
501 $out .= $this->addelement(1, $collapseIcon, $theData, ' class="c-headLineTable"', '');
504 // Render table rows only if in multi table view and not collapsed or if in single table view
505 if (!$listOnlyInSingleTableMode && (!$tableCollapsed || $this->table)) {
506 // Fixing a order table for sortby tables
507 $this->currentTable = array();
508 $currentIdList = array();
509 $doSort = ($TCA[$table]['ctrl']['sortby'] && !$this->sortField);
514 // Get first two rows and initialize prevPrevUid and prevUid if on page > 1
515 if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
516 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
517 $prevPrevUid = -(int) $row['uid'];
518 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
519 $prevUid = $row['uid'];
522 $accRows = array(); // Accumulate rows here
523 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
525 // In offline workspace, look for alternative record:
526 t3lib_BEfunc::workspaceOL($table, $row, $GLOBALS['BE_USER']->workspace, TRUE);
528 if (is_array($row)) {
530 $currentIdList[] = $row['uid'];
533 $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
534 $this->currentTable['next'][$prevUid] = '-'.$row['uid'];
535 $this->currentTable['prevUid'][$row['uid']] = $prevUid;
537 $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
538 $prevUid=$row['uid'];
542 $GLOBALS['TYPO3_DB']->sql_free_result($result);
544 $this->totalRowCount = count($accRows);
547 if ($this->csvOutput) $this->initCSV();
550 $this->CBnames=array();
551 $this->duplicateStack=array();
552 $this->eCounter=$this->firstElementNumber;
557 foreach($accRows as $row) {
558 // Render item row if counter < limit
559 if ($cc < $this->iLimit) {
561 $this->translations = FALSE;
562 $iOut.= $this->renderListRow($table,$row,$cc,$titleCol,$thumbsCol);
564 // 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:
565 if ($this->localizationView && $l10nEnabled) {
566 // For each available translation, render the record:
567 if (is_array($this->translations)) {
568 foreach ($this->translations as $lRow) {
569 // $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
570 if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) {
571 $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);
572 $lRow = is_array($tmpRow)?$tmpRow:$lRow;
574 // In offline workspace, look for alternative record:
575 t3lib_BEfunc::workspaceOL($table, $lRow, $GLOBALS['BE_USER']->workspace, true);
576 if (is_array($lRow) && $GLOBALS['BE_USER']->checkLanguageAccess($lRow[$TCA[$table]['ctrl']['languageField']])) {
577 $currentIdList[] = $lRow['uid'];
578 $iOut.=$this->renderListRow($table,$lRow,$cc,$titleCol,$thumbsCol,18);
585 // Counter of total rows incremented:
589 // Record navigation is added to the beginning and end of the table if in single table mode
591 $pageNavigation = $this->renderListNavigation();
592 $iOut = $pageNavigation . $iOut . $pageNavigation;
594 // show that there are more records than shown
595 if ($this->totalItems > $this->itemsLimitPerTable) {
596 $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems;
597 $hasMore = ($this->totalItems > $this->itemsLimitSingleTable);
598 $iOut .= '<tr><td colspan="' . count($this->fieldArray) . '" style="padding:5px;">
599 <a href="'.htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '">' .
600 '<img' . t3lib_iconWorks::skinImg($this->backPath,'gfx/pildown.gif', 'width="14" height="14"') .' alt="" />'.
601 ' <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a>
607 // The header row for the table is now created:
608 $out .= $this->renderListHeader($table,$currentIdList);
611 // The list of records is added after the header:
615 // ... and it is all wrapped in a table:
621 DB listing of elements: "'.htmlspecialchars($table).'"
623 <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist'.($listOnlyInSingleTableMode?' typo3-dblist-overview':'').'">
628 if ($this->csvOutput) $this->outputCSV($table); // This ends the page with exit.
636 * Rendering a single row for the list
638 * @param string Table name
639 * @param array Current record
640 * @param integer Counter, counting for each time an element is rendered (used for alternating colors)
641 * @param string Table field (column) where header value is found
642 * @param string Table field (column) where (possible) thumbnails can be found
643 * @param integer Indent from left.
644 * @return string Table row for the element
648 function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0) {
651 if (strlen($this->searchString)) { // If in search mode, make sure the preview will show the correct page
652 $id_orig = $this->id;
653 $this->id = $row['pid'];
656 if (is_array($row)) {
657 // add special classes for first and last row
659 if ($cc == 1 && $indent == 0) {
660 $rowSpecial .= ' firstcol';
662 if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
663 $rowSpecial .= ' lastcol';
666 // Background color, if any:
667 if ($this->alternateBgColors) {
668 $row_bgColor = ($cc%2) ? ' class="db_list_normal'.$rowSpecial.'"' : ' class="db_list_alt'.$rowSpecial.'"';
670 $row_bgColor = ' class="db_list_normal'.$rowSpecial.'"';
672 // Overriding with versions background color if any:
673 $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor;
678 // The icon with link
679 $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table);
680 $iconImg = t3lib_iconWorks::getIconImage($table,$row,$this->backPath,'title="'.htmlspecialchars($alttext).'"'.($indent ? ' style="margin-left: '.$indent.'px;"' : ''));
681 $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg;
683 // Preparing and getting the data-array
685 foreach($this->fieldArray as $fCol) {
686 if ($fCol==$titleCol) {
687 $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
688 // If the record is edit-locked by another user, we will show a little warning sign:
689 if (($lockInfo = t3lib_BEfunc::isRecordLocked($table, $row['uid']))) {
690 $warning = '<a href="#" onclick="' . htmlspecialchars('alert(' . $GLOBALS['LANG']->JScharCode($lockInfo['msg']) . '); return false;') . '">' .
691 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/recordlock_warning3.gif', 'width="17" height="12"') . ' title="' . htmlspecialchars($lockInfo['msg']) . '" alt="" />' .
694 $theData[$fCol] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row);
696 // Render thumbsnails if a thumbnail column exists and there is content in it:
697 if ($this->thumbs && trim($row[$thumbsCol])) {
698 $theData[$fCol] .= '<br />' . $this->thumbCode($row,$table,$thumbsCol);
701 $localizationMarkerClass = '';
702 if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField'])
703 && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0) {
704 // it's a translated record
705 $localizationMarkerClass = ' localization';
707 } elseif ($fCol == 'pid') {
708 $theData[$fCol]=$row[$fCol];
709 } elseif ($fCol == '_PATH_') {
710 $theData[$fCol]=$this->recPath($row['pid']);
711 } elseif ($fCol == '_REF_') {
712 $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']);
713 } elseif ($fCol == '_CONTROL_') {
714 $theData[$fCol]=$this->makeControl($table,$row);
715 } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') {
716 $theData[$fCol] = ' ';
717 } elseif ($fCol == '_CLIPBOARD_') {
718 $theData[$fCol]=$this->makeClip($table,$row);
719 } elseif ($fCol == '_LOCALIZATION_') {
720 list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row);
721 $theData[$fCol] = $lC1;
722 $theData[$fCol.'b'] = $lC2;
723 } elseif ($fCol == '_LOCALIZATION_b') {
724 // Do nothing, has been done above.
726 $tmpProc = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']);
727 $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
728 $row[$fCol] = $tmpProc;
732 if (strlen($this->searchString)) { // Reset the ID if it was overwritten
733 $this->id = $id_orig;
736 // Add row to CSV list:
737 if ($this->csvOutput) {
738 $this->addToCSV($row,$table);
741 // Add classes to table cells
742 $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass;
743 if (!$this->dontShowClipControlPanels) {
744 $this->addElement_tdCssClass['_CONTROL_'] = 'col-control';
745 $this->addElement_tdCssClass['_AFTERCONTROL_'] = 'col-control-space';
746 $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard';
748 $this->addElement_tdCssClass['_PATH_'] = 'col-path';
749 $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa';
750 $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb';
752 // Create element in table cells:
753 $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor);
755 // Finally, return table row element:
761 * Write sys_refindex entries for current record to $this->references
763 * @param string Table name
764 * @param integer Uid of current record
767 * @deprecated since 4.4: Use getReferenceCount instead
769 function setReferences($table, $uid) {
770 t3lib_div::logDeprecatedFunction();
772 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
773 'tablename, recuid, field',
775 'ref_table='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_refindex').
776 ' AND ref_uid='.intval($uid).
779 $this->references = $rows;
783 * Gets the number of records referencing the record with the UID $uid in
784 * the table $tableName.
786 * @param string $tableName
787 * table name of the referenced record, must not be empty
788 * @param integer $uid
789 * UID of the referenced record, must be > 0
791 * @return integer the number of references to record $uid in table
792 * $tableName, will be >= 0
794 protected function getReferenceCount($tableName, $uid) {
795 if (!isset($this->referenceCount[$tableName][$uid])) {
796 $numberOfReferences = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
799 'ref_table = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr(
800 $tableName, 'sys_refindex'
802 ' AND ref_uid = ' . $uid .
806 $this->referenceCount[$tableName][$uid] = $numberOfReferences;
809 return $this->referenceCount[$tableName][$uid];
813 * Rendering the header row for a table
815 * @param string Table name
816 * @param array Array of the currently displayed uids of the table
817 * @return string Header table row
821 function renderListHeader($table, $currentIdList) {
822 global $TCA, $LANG, $TYPO3_CONF_VARS;
827 // Traverse the fields:
828 foreach($this->fieldArray as $fCol) {
830 // Calculate users permissions to edit records in the table:
831 $permsEdit = $this->calcPerms & ($table=='pages'?2:16);
833 switch((string)$fCol) {
834 case '_PATH_': // Path
835 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._PATH_',1).']</i>';
837 case '_REF_': // References
838 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_mod_file_list.xml:c__REF_',1).']</i>';
840 case '_LOCALIZATION_': // Path
841 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._LOCALIZATION_',1).']</i>';
843 case '_LOCALIZATION_b': // Path
844 $theData[$fCol] = $LANG->getLL('Localize',1);
846 case '_CLIPBOARD_': // Clipboard:
849 // If there are elements on the clipboard for this table, then display the "paste into" icon:
850 $elFromTable = $this->clipObj->elFromTable($table);
851 if (count($elFromTable)) {
852 $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,$this->id)).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg('pages',$this->pageRow,'into',$elFromTable)).'">'.
853 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_paste',1).'" alt="" />'.
857 // If the numeric clipboard pads are enabled, display the control icons for that:
858 if ($this->clipObj->current!='normal') {
860 // The "select" link:
861 $cells['copyMarked']=$this->linkClipboardHeaderIcon('<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_copy.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_selectMarked',1).'" alt="" />',$table,'setCB');
863 // The "edit marked" link:
864 $editIdList = implode(',',$currentIdList);
865 $editIdList = "'+editList('".$table."','".$editIdList."')+'";
866 $params='&edit['.$table.']['.$editIdList.']=edit&disHelp=1';
867 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
868 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('clip_editMarked',1).'" alt="" />'.
871 // The "Delete marked" link:
872 $cells['delete']=$this->linkClipboardHeaderIcon('<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$LANG->getLL('clip_deleteMarked',1).'" alt="" />',$table,'delete',sprintf($LANG->getLL('clip_deleteMarkedWarning'),$LANG->sL($TCA[$table]['ctrl']['title'])));
874 // The "Select all" link:
875 $cells['markAll'] = '<a class="cbcCheckAll" rel="" href="#" onclick="' . htmlspecialchars('checkOffCB(\'' . implode(',', $this->CBnames) . '\', this); return false;') . '">' .
876 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_select.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_markRecords',1).'" alt="" />'.
882 * @hook renderListHeaderActions: Allows to change the clipboard icons of the Web>List table headers
884 * @request Bernhard Kraft <krafbt@kraftb.at>
885 * @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.
887 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
888 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
889 $hookObject = t3lib_div::getUserObj($classData);
890 if(!($hookObject instanceof localRecordList_actionsHook)) {
891 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567850);
893 $cells = $hookObject->renderListHeaderActions($table, $currentIdList, $cells, $this);
896 $theData[$fCol]=implode('',$cells);
898 case '_CONTROL_': // Control panel:
899 if (!$TCA[$table]['ctrl']['readOnly']) {
901 // If new records can be created on this page, add links:
902 if ($this->calcPerms&($table=='pages'?8:16) && $this->showNewRecLink($table)) {
903 if ($table=="tt_content" && $this->newWizards) {
904 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
905 $tmpTSc = t3lib_BEfunc::getModTSconfig($this->pageinfo['uid'],'mod.web_list');
906 $tmpTSc = $tmpTSc ['properties']['newContentWiz.']['overrideWithExtension'];
907 $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';
909 $icon = '<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$newContentWizScriptPath.'?id='.$this->id.'\');').'">'.
910 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new',1).'" alt="" />'.
912 } elseif ($table=='pages' && $this->newWizards) {
913 $icon = '<a href="'.htmlspecialchars($this->backPath.'db_new.php?id='.$this->id.'&pagesOnly=1&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
914 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new',1).'" alt="" />'.
918 $params = '&edit['.$table.']['.$this->id.']=new';
919 if ($table == 'pages_language_overlay') {
920 $params .= '&overrideVals[pages_language_overlay][doktype]=' . (int) $this->pageRow['doktype'];
922 $icon = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
923 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new',1).'" alt="" />'.
928 // If the table can be edited, add link for editing ALL SHOWN fields for all listed records:
929 if ($permsEdit && $this->table && is_array($currentIdList)) {
930 $editIdList = implode(',',$currentIdList);
931 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
932 $params = '&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.implode(',',$this->fieldArray).'&disHelp=1';
933 $icon .= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
934 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('editShownColumns',1).'" alt="" />'.
937 // add an empty entry, so column count fits again after moving this into $icon
938 $theData[$fCol] = ' ';
941 case '_AFTERCONTROL_': // space column
942 case '_AFTERREF_': // space column
943 $theData[$fCol] = ' ';
945 default: // Regular fields header:
947 if ($this->table && is_array($currentIdList)) {
949 // If the numeric clipboard pads are selected, show duplicate sorting link:
950 if ($this->clipNumPane()) {
951 $theData[$fCol].='<a href="'.htmlspecialchars($this->listURL('',-1).'&duplicateField='.$fCol).'">'.
952 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/select_duplicates.gif','width="11" height="11"').' title="'.$LANG->getLL('clip_duplicates',1).'" alt="" />'.
956 // If the table can be edited, add link for editing THIS field for all listed records:
957 if (!$TCA[$table]['ctrl']['readOnly'] && $permsEdit && $TCA[$table]['columns'][$fCol]) {
958 $editIdList = implode(',',$currentIdList);
959 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
960 $params='&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.$fCol.'&disHelp=1';
961 $iTitle = sprintf($LANG->getLL('editThisColumn'),rtrim(trim($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol))),':'));
962 $theData[$fCol].='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
963 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.htmlspecialchars($iTitle).'" alt="" />'.
967 $theData[$fCol].=$this->addSortLink($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol,'<i>[|]</i>')),$fCol,$table);
974 * @hook renderListHeader: Allows to change the contents of columns/cells of the Web>List table headers
976 * @request Bernhard Kraft <krafbt@kraftb.at>
977 * @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.
979 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
980 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
981 $hookObject = t3lib_div::getUserObj($classData);
982 if(!($hookObject instanceof localRecordList_actionsHook)) {
983 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567855);
985 $theData = $hookObject->renderListHeader($table, $currentIdList, $theData, $this);
989 // Create and return header table row:
990 return $this->addelement(1, $icon, $theData, ' class="c-headLine"', '');
994 * Creates a page browser for tables with many records
996 * @return string Navigation HTML
998 * @author Dmitry Pikhno <dpi@goldenplanet.com>
999 * @author Christian Kuhn <lolli@schwarzbu.ch>
1001 protected function renderListNavigation() {
1002 $totalPages = ceil($this->totalItems / $this->iLimit);
1006 // Show page selector if not all records fit into one page
1007 if ($totalPages > 1) {
1008 $first = $previous = $next = $last = $reload = '';
1009 $listURL = $this->listURL('', $this->table);
1012 $currentPage = floor(($this->firstElementNumber + 1) / $this->iLimit) + 1;
1014 // Compile first, previous, next, last and refresh buttons
1015 if ($currentPage > 1) {
1016 $labelFirst = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:first');
1018 $first = '<a href="' . $listURL . '&pointer=0">
1019 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_first.gif')
1020 . 'alt="' . $labelFirst . '" title="' . $labelFirst . '" />
1023 $first = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_first_disabled.gif') . 'alt="" title="" />';
1026 if (($currentPage - 1) > 0) {
1027 $labelPrevious = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:previous');
1029 $previous = '<a href="' . $listURL . '&pointer=' . (($currentPage - 2) * $this->iLimit) . '">
1030 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_previous.gif')
1031 . 'alt="' . $labelPrevious . '" title="' . $labelPrevious . '" />
1034 $previous = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_previous_disabled.gif') . 'alt="" title="" />';
1037 if (($currentPage + 1) <= $totalPages) {
1038 $labelNext = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:next');
1040 $next = '<a href="' . $listURL . '&pointer=' . (($currentPage) * $this->iLimit) . '">
1041 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_next.gif')
1042 . 'alt="' . $labelNext . '" title="' . $labelNext . '" />
1045 $next = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_next_disabled.gif') . 'alt="" title="" />';
1048 if ($currentPage != $totalPages) {
1049 $labelLast = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:last');
1051 $last = '<a href="' . $listURL . '&pointer=' . (($totalPages - 1) * $this->iLimit) . '">
1052 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_last.gif')
1053 . 'alt="' . $labelLast . '" title="' . $labelLast . '" />
1056 $last = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/control_last_disabled.gif') . 'alt="" title="" />';
1059 $reload = '<a href="#" onclick="document.dblistForm.action=\''
1060 . $listURL . '&pointer=\'+calculatePointer(); document.dblistForm.submit(); return true;">
1061 <img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/refresh_n.gif')
1062 . 'alt="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:reload')
1063 . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:reload')
1066 // Add js to traverse a page select input to a pointer value
1068 <script type="text/JavaScript">
1071 function calculatePointer(){
1072 page = document.getElementById(\'jumpPage\').value;
1074 if (page > ' . $totalPages . ') {
1075 page = ' . $totalPages . ';
1082 pointer = (page - 1) * ' . $this->iLimit . ';
1091 $pageNumberInput = '<span>
1092 <input type="text" value="' . $currentPage
1093 . '" size="3" id="jumpPage" name="jumpPage" onkeyup="if (event.keyCode == Event.KEY_RETURN) { document.dblistForm.action=\'' . $listURL . '&pointer=\'+calculatePointer(); document.dblistForm.submit(); } return true;" />
1095 $pageIndicator = '<span class="pageIndicator">'
1096 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:pageIndicator'), $pageNumberInput, $totalPages)
1099 if ($this->totalItems > ($this->firstElementNumber + $this->iLimit)) {
1100 $lastElementNumber = $this->firstElementNumber + $this->iLimit;
1102 $lastElementNumber = $this->totalItems;
1104 $rangeIndicator = '<span class="pageIndicator">'
1105 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:rangeIndicator'), $this->firstElementNumber + 1, $lastElementNumber)
1108 $content .= '<div id="typo3-dblist-pagination">'
1109 . $first . $previous
1110 . '<span class="bar"> </span>'
1111 . $rangeIndicator . '<span class="bar"> </span>'
1112 . $pageIndicator . '<span class="bar"> </span>'
1113 . $next . $last . '<span class="bar"> </span>'
1116 } // end of if pages > 1
1119 $titleColumn = $this->fieldArray[0];
1120 $data[$titleColumn] = $content;
1122 return ($this->addElement(1, '', $data));
1130 /*********************************
1132 * Rendering of various elements
1134 *********************************/
1137 * Creates the control panel for a single record in the listing.
1139 * @param string The table
1140 * @param array The record for which to make the control panel.
1141 * @return string HTML table with the control panel (unless disabled)
1143 function makeControl($table,$row) {
1144 global $TCA, $LANG, $SOBE, $TYPO3_CONF_VARS;
1146 if ($this->dontShowClipControlPanels) return '';
1149 t3lib_div::loadTCA($table);
1152 // If the listed table is 'pages' we have to request the permission settings for each page:
1153 if ($table=='pages') {
1154 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$row['uid']));
1157 // This expresses the edit permissions for this particular element:
1158 $permsEdit = ($table=='pages' && ($localCalcPerms&2)) || ($table!='pages' && ($this->calcPerms&16));
1160 // "Show" link (only pages and tt_content elements)
1161 if ($table=='pages' || $table=='tt_content') {
1162 $params='&edit['.$table.']['.$row['uid'].']=edit';
1163 $cells['view']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($table=='tt_content'?$this->id.'#'.$row['uid']:$row['uid'], $this->backPath)).'">'.
1164 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/zoom.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPage',1).'" alt="" />'.
1166 } elseif(!$this->table) {
1167 $cells['view'] = $this->spaceIcon;
1170 // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
1172 $params='&edit['.$table.']['.$row['uid'].']=edit';
1173 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
1174 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2'.(!$TCA[$table]['ctrl']['readOnly']?'':'_d').'.gif','width="11" height="12"').' title="'.$LANG->getLL('edit',1).'" alt="" />'.
1176 } elseif(!$this->table) {
1177 $cells['edit'] = $this->spaceIcon;
1180 // "Move" wizard link for pages/tt_content elements:
1181 if (($table=="tt_content" && $permsEdit) || ($table=='pages')) {
1182 $cells['move']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'move_el.php?table='.$table.'&uid='.$row['uid'].'\');').'">'.
1183 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/move_'.($table=='tt_content'?'record':'page').'.gif','width="11" height="12"').' title="'.$LANG->getLL('move_'.($table=='tt_content'?'record':'page'),1).'" alt="" />'.
1185 } elseif(!$this->table) {
1186 $cells['move'] = $this->spaceIcon;
1189 // If the extended control panel is enabled OR if we are seeing a single table:
1190 if ($SOBE->MOD_SETTINGS['bigControlPanel'] || $this->table) {
1192 // "Info": (All records)
1193 $cells['viewBig']='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$row['uid'].'\'); return false;').'">'.
1194 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/zoom2.gif','width="12" height="12"').' title="'.$LANG->getLL('showInfo',1).'" alt="" />'.
1197 // If the table is NOT a read-only table, then show these links:
1198 if (!$TCA[$table]['ctrl']['readOnly']) {
1200 // "Revert" link (history/undo)
1201 $cells['history']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$row['uid']).'\',\'#latest\');').'">'.
1202 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/history2.gif','width="13" height="12"').' title="'.$LANG->getLL('history',1).'" alt="" />'.
1206 if (t3lib_extMgm::isLoaded('version')) {
1207 $vers = t3lib_BEfunc::selectVersionsOfRecord($table, $row['uid'], 'uid', $GLOBALS['BE_USER']->workspace, FALSE, $row);
1208 if (is_array($vers)) { // If table can be versionized.
1209 if (count($vers)>1) {
1210 $class = 'typo3-ctrl-versioning-multipleVersions';
1211 $lab = count($vers)-1;
1213 $class = 'typo3-ctrl-versioning-oneVersion';
1217 $cells['version']='<a href="'.htmlspecialchars($this->backPath.t3lib_extMgm::extRelPath('version').'cm1/index.php?table='.rawurlencode($table).'&uid='.rawurlencode($row['uid'])).'" title="'.$LANG->getLL('displayVersions',1).'" class="typo3-ctrl-versioning ' . $class . '">'.
1220 } elseif(!$this->table) {
1221 $cells['version'] = '<span class="typo3-ctrl-versioning typo3-ctrl-versioning-hidden">V</span>';
1225 // "Edit Perms" link:
1226 if ($table=='pages' && $GLOBALS['BE_USER']->check('modules','web_perm')) {
1227 $cells['perms']='<a href="'.htmlspecialchars('mod/web/perm/index.php?id='.$row['uid'].'&return_id='.$row['uid'].'&edit=1').'">'.
1228 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/perm.gif','width="7" height="12"').' title="'.$LANG->getLL('permissions',1).'" alt="" />'.
1230 } elseif(!$this->table && $GLOBALS['BE_USER']->check('modules','web_perm')) {
1231 $cells['perms'] = $this->spaceIcon;
1234 // "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):
1235 if ($TCA[$table]['ctrl']['sortby'] || $TCA[$table]['ctrl']['useColumnsForDefaultValues']) {
1237 ($table!='pages' && ($this->calcPerms&16)) || // For NON-pages, must have permission to edit content on this parent page
1238 ($table=='pages' && ($this->calcPerms&8)) // For pages, must have permission to create new pages here.
1240 if ($this->showNewRecLink($table)) {
1241 $params='&edit['.$table.']['.(-($row['_MOVE_PLH']?$row['_MOVE_PLH_uid']:$row['uid'])).']=new';
1242 $cells['new']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
1243 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new'.($table=='pages'?'Page':'Record'),1).'" alt="" />'.
1247 } elseif(!$this->table) {
1248 $cells['new'] = $this->spaceIcon;
1252 if ($permsEdit && $TCA[$table]['ctrl']['sortby'] && !$this->sortField && !$this->searchLevels) {
1253 if (isset($this->currentTable['prev'][$row['uid']])) { // Up
1254 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prev'][$row['uid']];
1255 $cells['moveUp']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1256 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_up.gif','width="11" height="10"').' title="'.$LANG->getLL('moveUp',1).'" alt="" />'.
1259 $cells['moveUp'] = $this->spaceIcon;
1261 if ($this->currentTable['next'][$row['uid']]) { // Down
1262 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['next'][$row['uid']];
1263 $cells['moveDown']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1264 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_down.gif','width="11" height="10"').' title="'.$LANG->getLL('moveDown',1).'" alt="" />'.
1267 $cells['moveDown'] = $this->spaceIcon;
1269 } elseif(!$this->table) {
1270 $cells['moveUp'] = $this->spaceIcon;
1271 $cells['moveDown'] = $this->spaceIcon;
1274 // "Hide/Unhide" links:
1275 $hiddenField = $TCA[$table]['ctrl']['enablecolumns']['disabled'];
1276 if ($permsEdit && $hiddenField && $TCA[$table]['columns'][$hiddenField] && (!$TCA[$table]['columns'][$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$table.':'.$hiddenField))) {
1277 if ($row[$hiddenField]) {
1278 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=0';
1279 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1280 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_unhide.gif','width="11" height="10"').' title="'.$LANG->getLL('unHide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1283 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=1';
1284 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1285 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_hide.gif','width="11" height="10"').' title="'.$LANG->getLL('hide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1288 } elseif(!$this->table) {
1289 $cells['hide'] = $this->spaceIcon;
1293 if (($table=='pages' && ($localCalcPerms&4)) || ($table!='pages' && ($this->calcPerms&16))) {
1294 $titleOrig = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
1295 $title = t3lib_div::slashJS(t3lib_div::fixed_lgd_cs($titleOrig, $this->fixedL), 1);
1296 $params = '&cmd['.$table.']['.$row['uid'].'][delete]=1';
1298 $refCountMsg = t3lib_BEfunc::referenceCount(
1301 ' ' . $GLOBALS['LANG']->sL(
1302 'LLL:EXT:lang/locallang_core.xml:labels.referencesToRecord'
1304 $this->getReferenceCount($table, $row['uid'])
1306 t3lib_BEfunc::translationCount($table, $row['uid'], ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.translationsOfRecord'));
1307 $cells['delete']='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$LANG->JScharCode($LANG->getLL('deleteWarning').' "'. $title.'" '.$refCountMsg).')) {jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');} return false;').'">'.
1308 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$LANG->getLL('delete',1).'" alt="" />'.
1310 } elseif(!$this->table) {
1311 $cells['delete'] = $this->spaceIcon;
1314 // "Levels" links: Moving pages into new levels...
1315 if ($permsEdit && $table=='pages' && !$this->searchLevels) {
1317 // Up (Paste as the page right after the current parent page)
1318 if ($this->calcPerms&8) {
1319 $params='&cmd['.$table.']['.$row['uid'].'][move]='.-$this->id;
1320 $cells['moveLeft']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1321 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_left.gif','width="11" height="10"').' title="'.$LANG->getLL('prevLevel',1).'" alt="" />'.
1324 // Down (Paste as subpage to the page right above)
1325 if ($this->currentTable['prevUid'][$row['uid']]) {
1326 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$this->currentTable['prevUid'][$row['uid']]));
1327 if ($localCalcPerms&8) {
1328 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prevUid'][$row['uid']];
1329 $cells['moveRight']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1330 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_right.gif','width="11" height="10"').' title="'.$LANG->getLL('nextLevel',1).'" alt="" />'.
1333 $cells['moveRight'] = $this->spaceIcon;
1336 $cells['moveRight'] = $this->spaceIcon;
1338 } elseif(!$this->table) {
1339 $cells['moveLeft'] = $this->spaceIcon;
1340 $cells['moveRight'] = $this->spaceIcon;
1347 * @hook recStatInfoHooks: Allows to insert HTML before record icons on various places
1349 * @request Kasper Skaarhoj <kasper2007@typo3.com>
1351 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) {
1353 $_params = array($table,$row['uid']);
1354 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) {
1355 $stat.=t3lib_div::callUserFunction($_funcRef,$_params,$this);
1357 $cells['stat'] = $stat;
1360 * @hook makeControl: Allows to change control icons of records in list-module
1362 * @request Bernhard Kraft <krafbt@kraftb.at>
1363 * @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.
1365 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1366 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1367 $hookObject = t3lib_div::getUserObj($classData);
1368 if(!($hookObject instanceof localRecordList_actionsHook)) {
1369 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567840);
1371 $cells = $hookObject->makeControl($table, $row, $cells, $this);
1375 // Compile items into a DIV-element:
1377 <!-- CONTROL PANEL: '.$table.':'.$row['uid'].' -->
1378 <div class="typo3-DBctrl">'.implode('',$cells).'</div>';
1382 * Creates the clipboard panel for a single record in the listing.
1384 * @param string The table
1385 * @param array The record for which to make the clipboard panel.
1386 * @return string HTML table with the clipboard panel (unless disabled)
1388 function makeClip($table,$row) {
1389 global $TCA, $LANG, $TYPO3_CONF_VARS;
1391 // Return blank, if disabled:
1392 if ($this->dontShowClipControlPanels) return '';
1395 $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon;
1396 //enables to hide the copy, cut and paste icons for localized records - doesn't make much sense to perform these options for them
1397 $isL10nOverlay = $this->localizationView && $table != 'pages_language_overlay' && $row[$TCA[$table]['ctrl']['transOrigPointerField']] != 0;
1398 // Return blank, if disabled:
1399 // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel:
1400 if ($this->clipObj->current=='normal') { // For the "Normal" pad:
1402 // Show copy/cut icons:
1403 $isSel = (string)$this->clipObj->isSelected($table,$row['uid']);
1404 $cells['copy'] = $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'.
1405 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_copy'.($isSel=='copy'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.copy',1).'" alt="" />'.
1407 $cells['cut'] = $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'.
1408 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_cut'.($isSel=='cut'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.cut',1).'" alt="" />'.
1411 } else { // For the numeric clipboard pads (showing checkboxes where one can select elements on/off)
1413 // Setting name of the element in ->CBnames array:
1414 $n=$table.'|'.$row['uid'];
1415 $this->CBnames[]=$n;
1417 // Check if the current element is selected and if so, prepare to set the checkbox as selected:
1418 $checked = ($this->clipObj->isSelected($table,$row['uid'])?' checked="checked"':'');
1420 // If the "duplicateField" value is set then select all elements which are duplicates...
1421 if ($this->duplicateField && isset($row[$this->duplicateField])) {
1423 if (in_array($row[$this->duplicateField], $this->duplicateStack)) {
1424 $checked=' checked="checked"';
1426 $this->duplicateStack[] = $row[$this->duplicateField];
1429 // Adding the checkbox to the panel:
1430 $cells['select'] = $isL10nOverlay ? $this->spaceIcon : '<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />';
1433 // Now, looking for selected elements from the current table:
1434 $elFromTable = $this->clipObj->elFromTable($table);
1435 if (count($elFromTable) && $TCA[$table]['ctrl']['sortby']) { // IF elements are found and they can be individually ordered, then add a "paste after" icon:
1436 $cells['pasteAfter'] = $isL10nOverlay ? $this->spaceIcon : '<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,-$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'after',$elFromTable)).'">'.
1437 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteAfter',1).'" alt="" />'.
1441 // Now, looking for elements in general:
1442 $elFromTable = $this->clipObj->elFromTable('');
1443 if ($table=='pages' && count($elFromTable)) {
1444 $cells['pasteInto']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl('',$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'into',$elFromTable)).'">'.
1445 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteinto.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteInto',1).'" alt="" />'.
1450 * @hook makeClip: Allows to change clip-icons of records in list-module
1452 * @request Bernhard Kraft <krafbt@kraftb.at>
1453 * @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.
1455 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1456 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1457 $hookObject = t3lib_div::getUserObj($classData);
1458 if(!($hookObject instanceof localRecordList_actionsHook)) {
1459 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567845);
1461 $cells = $hookObject->makeClip($table, $row, $cells, $this);
1465 // Compile items into a DIV-element:
1466 return ' <!-- CLIPBOARD PANEL: '.$table.':'.$row['uid'].' -->
1467 <div class="typo3-clipCtrl">'.implode('',$cells).'</div>';
1471 * Make reference count
1473 * @param string Table name
1474 * @param integer UID of record
1475 * @return string HTML-table
1477 * @deprecated since 4.4: Use getReferenceHTML() instead
1479 function makeRef($table,$uid) {
1480 t3lib_div::logDeprecatedFunction();
1482 // Compile information for title tag:
1484 if (is_array($this->references)) {
1485 foreach ($this->references as $row) {
1486 $infoData[]=$row['tablename'].':'.$row['recuid'].':'.$row['field'];
1490 return count($infoData) ? '<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$uid.'\'); return false;').'" title="'.htmlspecialchars(t3lib_div::fixed_lgd_cs(implode(' / ',$infoData),100)).'">'.count($infoData).'</a>' : '';
1494 * Creates the HTML for a reference count for the record with the UID $uid
1495 * in the table $tableName.
1497 * @param string $tableName
1498 * table name of the referenced record, must not be empty
1499 * @param integer $uid
1500 * UID of the referenced record, must be > 0
1502 * @return string HTML of reference a link, will be empty if there are no
1503 * references to the corresponding record
1505 protected function createReferenceHtml($tableName, $uid) {
1506 $referenceCount = $this->getReferenceCount($tableName, $uid);
1507 if ($referenceCount == 0) {
1511 $queryResult = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1512 'tablename, recuid, field',
1514 'ref_table = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr(
1515 $tableName, 'sys_refindex'
1517 ' AND ref_uid = ' . $uid .
1524 $referenceTitles = array();
1526 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($queryResult)) {
1527 $referenceTitles[] = $row['tablename'] . ':' . $row['recuid'] .
1528 ':' . $row['field'];
1529 if (strlen(implode(' / ', $referenceTitles)) >= 100) {
1533 $GLOBALS['TYPO3_DB']->sql_free_result($queryResult);
1535 return '<a href="#" ' .
1536 'onclick="' . htmlspecialchars(
1537 'top.launchView(\'' . $tableName . '\', \'' . $uid .
1538 '\'); return false;'
1540 'title="' . htmlspecialchars(
1541 t3lib_div::fixed_lgd_cs(implode(' / ', $referenceTitles), 100)
1542 ) . '">' . $referenceCount . '</a>';
1546 * Creates the localization panel
1548 * @param string The table
1549 * @param array The record for which to make the localization panel.
1550 * @return array Array with key 0/1 with content for column 1 and 2
1552 function makeLocalizationPanel($table,$row) {
1560 $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList);
1561 $this->translations = $translations['translations'];
1563 // Language title and icon:
1564 $out[0] = $this->languageFlag($row[$TCA[$table]['ctrl']['languageField']]);
1566 if (is_array($translations)) {
1568 // Traverse page translations and add icon for each language that does NOT yet exist:
1570 foreach($this->pageOverlays as $lUid_OnPage => $lsysRec) {
1571 if (!isset($translations['translations'][$lUid_OnPage]) && $GLOBALS['BE_USER']->checkLanguageAccess($lUid_OnPage)) {
1572 $href = $this->backPath . $GLOBALS['TBE_TEMPLATE']->issueCommand(
1573 '&cmd['.$table.']['.$row['uid'].'][localize]='.$lUid_OnPage,
1574 $this->listURL().'&justLocalized='.rawurlencode($table.':'.$row['uid'].':'.$lUid_OnPage)
1577 $lC = ($this->languageIconTitles[$lUid_OnPage]['flagIcon'] ? '<img src="'.$this->languageIconTitles[$lUid_OnPage]['flagIcon'].'" class="absmiddle" alt="" />' : $this->languageIconTitles[$lUid_OnPage]['title']);
1578 $lC = '<a href="'.htmlspecialchars($href).'">'.$lC.'</a> ';
1584 if ($lNew) $out[1].= $lNew;
1586 $out[0] = ' '.$out[0];
1594 * Create the selector box for selecting fields to display from a table:
1596 * @param string Table name
1597 * @param boolean If true, form-fields will be wrapped around the table.
1598 * @return string HTML table with the selector box (name: displayFields['.$table.'][])
1600 function fieldSelectBox($table,$formFields=1) {
1604 t3lib_div::loadTCA($table);
1605 $formElements=array('','');
1607 $formElements=array('<form action="'.htmlspecialchars($this->listURL()).'" method="post">','</form>');
1610 // Load already selected fields, if any:
1611 $setFields=is_array($this->setFields[$table]) ? $this->setFields[$table] : array();
1613 // Request fields from table:
1614 $fields = $this->makeFieldList($table, false, true);
1616 // Add pseudo "control" fields
1619 $fields[]='_LOCALIZATION_';
1620 $fields[]='_CONTROL_';
1621 $fields[]='_CLIPBOARD_';
1623 // Create an option for each field:
1625 $opt[] = '<option value=""></option>';
1626 foreach($fields as $fN) {
1627 $fL = is_array($TCA[$table]['columns'][$fN]) ? rtrim($LANG->sL($TCA[$table]['columns'][$fN]['label']),':') : '['.$fN.']'; // Field label
1629 <option value="'.$fN.'"'.(in_array($fN,$setFields)?' selected="selected"':'').'>'.htmlspecialchars($fL).'</option>';
1632 // Compile the options into a multiple selector box:
1634 <select size="'.t3lib_div::intInRange(count($fields)+1,3,20).'" multiple="multiple" name="displayFields['.$table.'][]">'.implode('',$opt).'
1638 // Table with the field selector::
1640 '.$formElements[0].'
1643 Field selector for extended table view:
1645 <table border="0" cellpadding="0" cellspacing="0" class="bgColor4" id="typo3-dblist-fieldSelect">
1648 <td><input type="submit" name="search" value="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.setFields',1).'" /></td>
1665 /*********************************
1669 *********************************/
1672 * Creates a link around $string. The link contains an onclick action which submits the script with some clipboard action.
1673 * Currently, this is used for setting elements / delete elements.
1675 * @param string The HTML content to link (image/text)
1676 * @param string Table name
1677 * @param string Clipboard command (eg. "setCB" or "delete")
1678 * @param string Warning text, if any ("delete" uses this for confirmation)
1679 * @return string <a> tag wrapped link.
1681 function linkClipboardHeaderIcon($string,$table,$cmd,$warning='') {
1682 $onClickEvent = 'document.dblistForm.cmd.value=\''.$cmd.'\';document.dblistForm.cmd_table.value=\''.$table.'\';document.dblistForm.submit();';
1683 if ($warning) $onClickEvent = 'if (confirm('.$GLOBALS['LANG']->JScharCode($warning).')){'.$onClickEvent.'}';
1684 return '<a href="#" onclick="'.htmlspecialchars($onClickEvent.'return false;').'">'.$string.'</a>';
1688 * Returns true if a numeric clipboard pad is selected/active
1692 function clipNumPane() {
1693 return in_Array('_CLIPBOARD_',$this->fieldArray) && $this->clipObj->current!='normal';
1697 * Creates a sort-by link on the input string ($code).
1698 * It will automatically detect if sorting should be ascending or descending depending on $this->sortRev.
1699 * Also some fields will not be possible to sort (including if single-table-view is disabled).
1701 * @param string The string to link (text)
1702 * @param string The fieldname represented by the title ($code)
1703 * @param string Table name
1704 * @return string Linked $code variable
1706 function addSortLink($code,$field,$table) {
1708 // Certain circumstances just return string right away (no links):
1709 if ($field=='_CONTROL_' || $field=='_LOCALIZATION_' || $field=='_CLIPBOARD_' || $field=='_REF_' || $this->disableSingleTableView) return $code;
1711 // If "_PATH_" (showing record path) is selected, force sorting by pid field (will at least group the records!)
1712 if ($field=='_PATH_') $field=pid;
1714 // Create the sort link:
1715 $sortUrl = $this->listURL('',-1,'sortField,sortRev,table').'&table='.$table.'&sortField='.$field.'&sortRev='.($this->sortRev || ($this->sortField!=$field)?0:1);
1716 $sortArrow = ($this->sortField==$field?'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/red'.($this->sortRev?'up':'down').'.gif','width="7" height="4"').' alt="" />':'');
1718 // Return linked field:
1719 return '<a href="'.htmlspecialchars($sortUrl).'">'.$code.
1725 * Returns the path for a certain pid
1726 * The result is cached internally for the session, thus you can call this function as much as you like without performance problems.
1728 * @param integer The page id for which to get the path
1729 * @return string The path.
1731 function recPath($pid) {
1732 if (!isset($this->recPath_cache[$pid])) {
1733 $this->recPath_cache[$pid] = t3lib_BEfunc::getRecordPath($pid,$this->perms_clause,20);
1735 return $this->recPath_cache[$pid];
1739 * Returns true if a link for creating new records should be displayed for $table
1741 * @param string Table name
1742 * @return boolean Returns true if a link for creating new records should be displayed for $table
1743 * @see SC_db_new::showNewRecLink
1745 function showNewRecLink($table) {
1746 // No deny/allow tables are set:
1747 if (!count($this->allowedNewTables) && !count($this->deniedNewTables)) {
1749 // If table is not denied (which takes precedence over allowed tables):
1750 } elseif (!in_array($table, $this->deniedNewTables) && (!count($this->allowedNewTables) || in_array($table, $this->allowedNewTables))) {
1752 // If table is denied or allowed tables are set, but table is not part of:
1759 * 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.
1760 * Uses REQUEST_URI as value.
1764 function makeReturnUrl() {
1765 return '&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
1778 /************************************
1780 * CSV related functions
1782 ************************************/
1785 * Initializes internal csvLines array with the header of field names
1789 function initCSV() {
1792 $this->csvLines=array();
1794 // Getting header line with field names:
1796 foreach ($this->fieldArray as $fN) {
1797 if ($fN == '_CONTROL_' || $fN == '_CLIPBOARD_') {
1803 // Set the header + an empty row:
1804 $this->setCsvRow($csvRow);
1805 $this->csvLines[] = '';
1810 * Adds the content of input array $row to the CSV list:
1812 * @param array Record array, from which the values of fields found in $this->fieldArray will be listed in the CSV output.
1813 * @param string Table name
1816 function addToCSV($row,$table) {
1818 // Traversing fields, adding values from $row:
1820 foreach ($this->fieldArray as $fN) {
1823 $csvRow[] = $this->recPath($row['pid']);
1827 $csvRow[] = $this->createReferenceHtml($table, $row['uid']);
1830 // remove these columns from the CSV view
1837 $csvRow[] = $row[$fN];
1841 // Set the values in the CSV list
1842 $this->setCsvRow($csvRow);
1847 * Adds input row of values to the internal csvLines array as a CSV formatted line
1849 * @param array Array with values to be listed.
1852 function setCsvRow($csvRow) {
1853 $this->csvLines[] = t3lib_div::csvValues($csvRow);
1857 * Compiles the internal csvLines array to a csv-string and outputs it to the browser.
1858 * This function exits!
1860 * @param string Filename prefix:
1861 * @return void EXITS php execusion!
1863 function outputCSV($prefix) {
1865 // Setting filename:
1866 $filename=$prefix.'_'.date('dmy-Hi').'.csv';
1868 // Creating output header:
1869 $mimeType = 'application/octet-stream';
1870 Header('Content-Type: '.$mimeType);
1871 Header('Content-Disposition: attachment; filename='.$filename);
1873 // Printing the content of the CSV lines:
1874 echo implode(chr(13).chr(10),$this->csvLines);
1883 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']) {
1884 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']);