2 /*************************************************************
5 * (c) 1999-2008 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 * Create the panel of buttons for submitting the form or otherwise perform operations.
125 * @return array all available buttons as an assoc. array
127 public function getButtons() {
147 // Get users permissions for this page record:
148 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms($this->pageRow);
151 if (!strlen($this->id)) {
152 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_noId', $GLOBALS['BACK_PATH']);
153 } elseif(!$this->id) {
154 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_root', $GLOBALS['BACK_PATH']);
156 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module', $GLOBALS['BACK_PATH']);
159 if (isset($this->id)) {
161 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewOnClick($this->id, $this->backPath, t3lib_BEfunc::BEgetRootLine($this->id))) . '">' .
162 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/zoom.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', 1) . '" alt="" />' .
166 if (!$GLOBALS['SOBE']->modTSconfig['properties']['noCreateRecordsLink']) {
167 $buttons['new_record'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'db_new.php?id=' . $this->id . '\');') . '">' .
168 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/new_el.gif') . ' title="' . $LANG->getLL('newRecordGeneral', 1) . '" alt="" />' .
172 // If edit permissions are set (see class.t3lib_userauthgroup.php)
173 if ($localCalcPerms&2 && !empty($this->id)) {
176 $params = '&edit[pages][' . $this->pageRow['uid'] . ']=edit';
177 $buttons['edit'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) . '">' .
178 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/edit2.gif') . ' title="' . $LANG->getLL('editPage', 1) . '" alt="" />' .
181 if ($this->pageRow['hidden']) {
182 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=0';
183 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '">' .
184 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/button_unhide.gif') . ' title="' . $LANG->getLL('unHidePage', 1) . '" alt="" />' .
188 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=1';
189 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '">'.
190 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/button_hide.gif') . ' title="' . $LANG->getLL('hidePage', 1) . '" alt="" />' .
195 $buttons['move'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'move_el.php?table=pages&uid=' . $this->pageRow['uid'] . '\');') . '">' .
196 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/move_' . ($this->table == 'tt_content' ? 'record' : 'page') . '.gif') . ' title="' . $LANG->getLL('move_page', 1) . '" alt="" />' .
200 $buttons['level_up'] = '<a href="' . htmlspecialchars($this->listURL($this->pageRow['pid'])) . '" onclick="setHighlight(' . $this->pageRow['pid'] . ')">' .
201 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/i/pages_up.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.upOneLevel', 1) . '" alt="" />' .
208 if (($localCalcPerms&8) || ($localCalcPerms&16)) {
209 $elFromTable = $this->clipObj->elFromTable('');
210 if (count($elFromTable)) {
211 $buttons['paste'] = '<a href="' . htmlspecialchars($this->clipObj->pasteUrl('', $this->id)) . '" onclick="' . htmlspecialchars('return ' . $this->clipObj->confirmMsg('pages', $this->pageRow, 'into', $elFromTable)) . '">' .
212 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clip_pasteafter.gif') . ' title="' . $LANG->getLL('clip_paste', 1) . '" alt="" />' .
218 $buttons['cache'] = '<a href="' . htmlspecialchars($this->listURL() . '&clear_cache=1') . '">' .
219 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clear_cache.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.clear_cache', 1) . '" alt="" />' .
225 $buttons['csv'] = '<a href="' . htmlspecialchars($this->listURL() . '&csv=1') . '">' .
226 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/csv.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.csv', 1) . '" alt="" />' .
230 if (t3lib_extMgm::isLoaded('impexp')) {
231 $buttons['export'] = '<a href="' . htmlspecialchars($this->backPath. 'mod.php?M=xMOD_tximpexp&tx_impexp[action]=export&tx_impexp[list][]=' . rawurlencode($this->table . ':' . $this->id)) . '">' .
232 '<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="" />' .
239 $buttons['reload'] = '<a href="' . htmlspecialchars($this->listURL()) . '">' .
240 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/refresh_n.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.reload', 1) . '" alt="" />' .
244 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
245 $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');
249 if ($this->returnUrl) {
250 $buttons['back'] = '<a href="' . htmlspecialchars(t3lib_div::linkThisUrl($this->returnUrl, array('id' => $this->id))) . '" class="typo3-goBack">' .
251 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/goback.gif') . ' title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.goBack', 1) . '" alt="" />' .
260 * Creates the listing of records from a single table
262 * @param string Table name
263 * @param integer Page id
264 * @param string List of fields to show in the listing. Pseudo fields will be added including the record header.
265 * @return string HTML table with the listing for the record.
267 function getTable($table,$id,$rowlist) {
268 global $TCA, $TYPO3_CONF_VARS;
270 // Loading all TCA details for this table:
271 t3lib_div::loadTCA($table);
275 $titleCol = $TCA[$table]['ctrl']['label'];
276 $thumbsCol = $TCA[$table]['ctrl']['thumbnail'];
277 $l10nEnabled = $TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField'] && !$TCA[$table]['ctrl']['transOrigPointerTable'];
279 // prepare space icon
280 $iconWidth = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeWidth'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeWidth'] : 12;
281 $iconHeight = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeHeight'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['iconSizeHeight'] : 12;
282 $this->spaceIcon = '<img src="' . $this->backPath . 'clear.gif" width="' . $iconWidth . '" height="' . $iconHeight . '" title="" alt="" />';
284 // Cleaning rowlist for duplicates and place the $titleCol as the first column always!
285 $this->fieldArray=array();
287 $this->fieldArray[] = $titleCol; // Add title column
289 if (!t3lib_div::inList($rowlist,'_CONTROL_')) {
290 $this->fieldArray[] = '_CONTROL_';
291 $this->fieldArray[] = '_AFTERCONTROL_';
294 if ($this->showClipboard) {
295 $this->fieldArray[] = '_CLIPBOARD_';
298 if (!$this->dontShowClipControlPanels) {
299 $this->fieldArray[]='_REF_';
300 $this->fieldArray[]='_AFTERREF_';
303 if ($this->searchLevels) {
304 $this->fieldArray[]='_PATH_';
307 if ($this->localizationView && $l10nEnabled) {
308 $this->fieldArray[] = '_LOCALIZATION_';
309 $this->fieldArray[] = '_LOCALIZATION_b';
311 '.$TCA[$table]['ctrl']['languageField'].'<=0
313 '.$TCA[$table]['ctrl']['transOrigPointerField'].' = 0
317 $this->fieldArray=array_unique(array_merge($this->fieldArray,t3lib_div::trimExplode(',',$rowlist,1)));
318 if ($this->noControlPanels) {
319 $tempArray = array_flip($this->fieldArray);
320 unset($tempArray['_CONTROL_']);
321 unset($tempArray['_CLIPBOARD_']);
322 $this->fieldArray = array_keys($tempArray);
325 // Creating the list of fields to include in the SQL query:
326 $selectFields = $this->fieldArray;
327 $selectFields[] = 'uid';
328 $selectFields[] = 'pid';
329 if ($thumbsCol) $selectFields[] = $thumbsCol; // adding column for thumbnails
330 if ($table=='pages') {
331 if (t3lib_extMgm::isLoaded('cms')) {
332 $selectFields[] = 'module';
333 $selectFields[] = 'extendToSubpages';
334 $selectFields[] = 'nav_hide';
336 $selectFields[] = 'doktype';
338 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) {
339 $selectFields = array_merge($selectFields,$TCA[$table]['ctrl']['enablecolumns']);
341 if ($TCA[$table]['ctrl']['type']) {
342 $selectFields[] = $TCA[$table]['ctrl']['type'];
344 if ($TCA[$table]['ctrl']['typeicon_column']) {
345 $selectFields[] = $TCA[$table]['ctrl']['typeicon_column'];
347 if ($TCA[$table]['ctrl']['versioningWS']) {
348 $selectFields[] = 't3ver_id';
349 $selectFields[] = 't3ver_state';
350 $selectFields[] = 't3ver_wsid';
351 $selectFields[] = 't3ver_swapmode'; // Filtered out when pages in makeFieldList()
354 $selectFields[] = $TCA[$table]['ctrl']['languageField'];
355 $selectFields[] = $TCA[$table]['ctrl']['transOrigPointerField'];
357 if ($TCA[$table]['ctrl']['label_alt']) {
358 $selectFields = array_merge($selectFields,t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['label_alt'],1));
360 $selectFields = array_unique($selectFields); // Unique list!
361 $selectFields = array_intersect($selectFields,$this->makeFieldList($table,1)); // Making sure that the fields in the field-list ARE in the field-list from TCA!
362 $selFieldList = implode(',',$selectFields); // implode it into a list of fields for the SQL-statement.
365 * @hook DB-List getTable
367 * @request Malte Jansen <mail@maltejansen.de>
369 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) {
370 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) {
371 $hookObject = &t3lib_div::getUserObj($classData);
373 if(!($hookObject instanceof t3lib_localRecordListGetTableHook)) {
374 throw new UnexpectedValueException('$hookObject must implement interface t3lib_localRecordListGetTableHook', 1195114460);
377 $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this);
381 // Create the SQL query for selecting the elements in the listing:
382 if ($this->csvOutput) { // do not do paging when outputting as CSV
386 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc)
387 $this->setTotalItems($queryParts); // Finding the total amount of records on the page (API function from class.db_list.inc)
393 // If the count query returned any number of records, we perform the real query, selecting records.
394 if ($this->totalItems) {
395 // set the showLimit to the number of records when outputting as CSV
396 if ($this->csvOutput) {
397 $this->showLimit = $this->totalItems;
398 $this->iLimit = $this->totalItems;
400 $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
401 $dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result);
404 $LOISmode = $this->listOnlyInSingleTableMode && !$this->table;
406 // If any records was selected, render the list:
409 // Half line is drawn between tables:
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 // Header line is drawn
422 if ($this->disableSingleTableView) {
423 $theData[$titleCol] = '<span class="c-table">'.$GLOBALS['LANG']->sL($TCA[$table]['ctrl']['title'],1).'</span> ('.$this->totalItems.')';
425 $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="" />');
429 $theData[$titleCol].= t3lib_BEfunc::cshItem($table,'',$this->backPath,'',FALSE,'margin-bottom:0px; white-space: normal;');
434 <td class="c-headLineTable" style="width:95%;">'.$theData[$titleCol].'</td>
437 if ($GLOBALS['BE_USER']->uc["edit_showFieldHelp"]) {
438 $GLOBALS['LANG']->loadSingleTableDescription($table);
439 if (isset($GLOBALS['TCA_DESCR'][$table]['columns'][''])) {
440 $onClick = 'vHWin=window.open(\'view_help.php?tfID='.$table.'.\',\'viewFieldHelp\',\'height=400,width=600,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;';
443 <td class="c-tableDescription">'.t3lib_BEfunc::helpTextIcon($table,'',$this->backPath,TRUE).$GLOBALS['TCA_DESCR'][$table]['columns']['']['description'].'</td>
448 $theUpIcon = ($table=='pages'&&$this->id&&isset($this->pageRow['pid'])) ? '<a href="'.htmlspecialchars($this->listURL($this->pageRow['pid'])).'" onclick="setHighlight('.$this->pageRow['pid'].')"><img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/i/pages_up.gif','width="18" height="16"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.upOneLevel',1).'" alt="" /></a>':'';
449 $out.=$this->addelement(1,$theUpIcon,$theData,' class="c-headLineTable"','');
453 // Fixing a order table for sortby tables
454 $this->currentTable = array();
455 $currentIdList = array();
456 $doSort = ($TCA[$table]['ctrl']['sortby'] && !$this->sortField);
460 $accRows = array(); // Accumulate rows here
461 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
463 // In offline workspace, look for alternative record:
464 t3lib_BEfunc::workspaceOL($table, $row, $GLOBALS['BE_USER']->workspace, TRUE);
466 if (is_array($row)) {
468 $currentIdList[] = $row['uid'];
471 $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
472 $this->currentTable['next'][$prevUid] = '-'.$row['uid'];
473 $this->currentTable['prevUid'][$row['uid']] = $prevUid;
475 $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
476 $prevUid=$row['uid'];
480 $GLOBALS['TYPO3_DB']->sql_free_result($result);
482 $this->totalRowCount = count($accRows);
485 if ($this->csvOutput) $this->initCSV();
488 $this->CBnames=array();
489 $this->duplicateStack=array();
490 $this->eCounter=$this->firstElementNumber;
494 foreach($accRows as $row) {
496 // Forward/Backwards navigation links:
497 list($flag,$code) = $this->fwd_rwd_nav($table);
500 // If render item, increment counter and call function
503 $iOut.= $this->renderListRow($table,$row,$cc,$titleCol,$thumbsCol);
505 // 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:
506 if ($this->localizationView && $l10nEnabled) {
508 // Look for translations of this record:
509 $translations = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
513 ' AND '.$TCA[$table]['ctrl']['languageField'].'>0'.
514 ' AND '.$TCA[$table]['ctrl']['transOrigPointerField'].'='.intval($row['uid']).
515 t3lib_BEfunc::deleteClause($table).
516 t3lib_BEfunc::versioningPlaceholderClause($table)
519 // For each available translation, render the record:
520 if (is_array($translations)) {
521 foreach($translations as $lRow) {
522 // In offline workspace, look for alternative record:
523 t3lib_BEfunc::workspaceOL($table, $lRow, $GLOBALS['BE_USER']->workspace);
525 if (is_array($lRow) && $GLOBALS['BE_USER']->checkLanguageAccess($lRow[$TCA[$table]['ctrl']['languageField']])) {
526 $currentIdList[] = $lRow['uid'];
527 $iOut.=$this->renderListRow($table,$lRow,$cc,$titleCol,$thumbsCol,18);
534 // Counter of total rows incremented:
538 // The header row for the table is now created:
539 $out.=$this->renderListHeader($table,$currentIdList);
542 // The list of records is added after the header:
545 // ... and it is all wrapped in a table:
551 DB listing of elements: "'.htmlspecialchars($table).'"
553 <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist'.($LOISmode?' typo3-dblist-overview':'').'">
558 if ($this->csvOutput) $this->outputCSV($table); // This ends the page with exit.
566 * Rendering a single row for the list
568 * @param string Table name
569 * @param array Current record
570 * @param integer Counter, counting for each time an element is rendered (used for alternating colors)
571 * @param string Table field (column) where header value is found
572 * @param string Table field (column) where (possible) thumbnails can be found
573 * @param integer Indent from left.
574 * @return string Table row for the element
578 function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0) {
581 if (strlen($this->searchString)) { // If in search mode, make sure the preview will show the correct page
582 $id_orig = $this->id;
583 $this->id = $row['pid'];
586 if (is_array($row)) {
588 // add special classes for first and last row
590 if ($cc == 1 && $indent == 0) {
591 $rowSpecial .= ' firstcol';
593 if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
594 $rowSpecial .= ' lastcol';
597 // Background color, if any:
598 if ($this->alternateBgColors) {
599 $row_bgColor = ($cc%2) ? ' class="db_list_normal'.$rowSpecial.'"' : ' class="db_list_alt'.$rowSpecial.'"';
601 $row_bgColor = ' class="db_list_normal'.$rowSpecial.'"';
603 // Overriding with versions background color if any:
604 $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor;
609 // The icon with link
610 $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table);
611 $iconImg = t3lib_iconWorks::getIconImage($table,$row,$this->backPath,'title="'.htmlspecialchars($alttext).'"'.($indent ? ' style="margin-left: '.$indent.'px;"' : ''));
612 $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg;
614 // Preparing and getting the data-array
616 foreach($this->fieldArray as $fCol) {
617 if ($fCol==$titleCol) {
618 $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
619 $theData[$fCol] = $this->linkWrapItems($table,$row['uid'],$recTitle,$row);
620 } elseif ($fCol == 'pid') {
621 $theData[$fCol]=$row[$fCol];
622 } elseif ($fCol == '_PATH_') {
623 $theData[$fCol]=$this->recPath($row['pid']);
624 } elseif ($fCol == '_REF_') {
625 $theData[$fCol]=$this->makeRef($table,$row['uid']);
626 } elseif ($fCol == '_CONTROL_') {
627 $theData[$fCol]=$this->makeControl($table,$row);
628 } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') {
629 $theData[$fCol] = ' ';
630 } elseif ($fCol == '_CLIPBOARD_') {
631 $theData[$fCol]=$this->makeClip($table,$row);
632 } elseif ($fCol == '_LOCALIZATION_') {
633 list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row);
634 $theData[$fCol] = $lC1;
635 $theData[$fCol.'b'] = $lC2;
636 } elseif ($fCol == '_LOCALIZATION_b') {
637 // Do nothing, has been done above.
639 $tmpProc = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']);
640 $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
641 $row[$fCol] = $tmpProc;
645 if (strlen($this->searchString)) { // Reset the ID if it was overwritten
646 $this->id = $id_orig;
649 // Add row to CSV list:
650 if ($this->csvOutput) {
651 $this->addToCSV($row,$table);
654 // Add classes to table cells
655 $this->addElement_tdCssClass[$titleCol] = 'col-title';
656 if (!$this->dontShowClipControlPanels) {
657 $this->addElement_tdCssClass['_CONTROL_'] = 'col-control';
658 $this->addElement_tdCssClass['_AFTERCONTROL_'] = 'col-control-space';
659 $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard';
661 $this->addElement_tdCssClass['_PATH_'] = 'col-path';
662 $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa';
663 $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb';
666 // Create element in table cells:
667 $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor);
669 // Render thumbsnails if a thumbnail column exists and there is content in it:
670 if ($this->thumbs && trim($row[$thumbsCol])) {
671 $iOut.=$this->addelement(4,'', Array($titleCol=>$this->thumbCode($row,$table,$thumbsCol)),$row_bgColor);
674 // Finally, return table row element:
680 * Rendering the header row for a table
682 * @param string Table name
683 * @param array Array of the currently displayed uids of the table
684 * @return string Header table row
688 function renderListHeader($table, $currentIdList) {
689 global $TCA, $LANG, $TYPO3_CONF_VARS;
694 // Traverse the fields:
695 foreach($this->fieldArray as $fCol) {
697 // Calculate users permissions to edit records in the table:
698 $permsEdit = $this->calcPerms & ($table=='pages'?2:16);
700 switch((string)$fCol) {
701 case '_PATH_': // Path
702 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._PATH_',1).']</i>';
704 case '_REF_': // References
705 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_mod_file_list.xml:c__REF_',1).']</i>';
707 case '_LOCALIZATION_': // Path
708 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._LOCALIZATION_',1).']</i>';
710 case '_LOCALIZATION_b': // Path
711 $theData[$fCol] = $LANG->getLL('Localize',1);
713 case '_CLIPBOARD_': // Clipboard:
716 // If there are elements on the clipboard for this table, then display the "paste into" icon:
717 $elFromTable = $this->clipObj->elFromTable($table);
718 if (count($elFromTable)) {
719 $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,$this->id)).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg('pages',$this->pageRow,'into',$elFromTable)).'">'.
720 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_paste',1).'" alt="" />'.
724 // If the numeric clipboard pads are enabled, display the control icons for that:
725 if ($this->clipObj->current!='normal') {
727 // The "select" link:
728 $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');
730 // The "edit marked" link:
731 $editIdList = implode(',',$currentIdList);
732 $editIdList = "'+editList('".$table."','".$editIdList."')+'";
733 $params='&edit['.$table.']['.$editIdList.']=edit&disHelp=1';
734 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
735 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('clip_editMarked',1).'" alt="" />'.
738 // The "Delete marked" link:
739 $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'])));
741 // The "Select all" link:
742 $cells['markAll']='<a href="#" onclick="'.htmlspecialchars('checkOffCB(\''.implode(',',$this->CBnames).'\'); return false;').'">'.
743 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_select.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_markRecords',1).'" alt="" />'.
749 * @hook renderListHeaderActions: Allows to change the clipboard icons of the Web>List table headers
751 * @request Bernhard Kraft <krafbt@kraftb.at>
752 * @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.
754 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
755 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
756 $hookObject = &t3lib_div::getUserObj($classData);
757 if(!($hookObject instanceof localRecordList_actionsHook)) {
758 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567850);
760 $cells = $hookObject->renderListHeaderActions($table, $currentIdList, $cells, $this);
763 $theData[$fCol]=implode('',$cells);
765 case '_CONTROL_': // Control panel:
766 if (!$TCA[$table]['ctrl']['readOnly']) {
768 // If new records can be created on this page, add links:
769 if ($this->calcPerms&($table=='pages'?8:16) && $this->showNewRecLink($table)) {
770 if ($table=="tt_content" && $this->newWizards) {
771 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
772 $tmpTSc = t3lib_BEfunc::getModTSconfig($this->pageinfo['uid'],'mod.web_list');
773 $tmpTSc = $tmpTSc ['properties']['newContentWiz.']['overrideWithExtension'];
774 $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';
776 $icon = '<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$newContentWizScriptPath.'?id='.$this->id.'\');').'">'.
777 '<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="" />'.
779 } elseif ($table=='pages' && $this->newWizards) {
780 $icon = '<a href="'.htmlspecialchars($this->backPath.'db_new.php?id='.$this->id.'&pagesOnly=1&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.
781 '<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="" />'.
785 $params = '&edit['.$table.']['.$this->id.']=new';
786 $icon = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
787 '<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="" />'.
792 // If the table can be edited, add link for editing ALL SHOWN fields for all listed records:
793 if ($permsEdit && $this->table && is_array($currentIdList)) {
794 $editIdList = implode(',',$currentIdList);
795 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
796 $params = '&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.implode(',',$this->fieldArray).'&disHelp=1';
797 $icon .= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
798 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$LANG->getLL('editShownColumns',1).'" alt="" />'.
801 // add an empty entry, so column count fits again after moving this into $icon
802 $theData[$fCol] = ' ';
805 case '_AFTERCONTROL_': // space column
806 case '_AFTERREF_': // space column
807 $theData[$fCol] = ' ';
809 default: // Regular fields header:
811 if ($this->table && is_array($currentIdList)) {
813 // If the numeric clipboard pads are selected, show duplicate sorting link:
814 if ($this->clipNumPane()) {
815 $theData[$fCol].='<a href="'.htmlspecialchars($this->listURL('',-1).'&duplicateField='.$fCol).'">'.
816 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/select_duplicates.gif','width="11" height="11"').' title="'.$LANG->getLL('clip_duplicates',1).'" alt="" />'.
820 // If the table can be edited, add link for editing THIS field for all listed records:
821 if (!$TCA[$table]['ctrl']['readOnly'] && $permsEdit && $TCA[$table]['columns'][$fCol]) {
822 $editIdList = implode(',',$currentIdList);
823 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'";
824 $params='&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.$fCol.'&disHelp=1';
825 $iTitle = sprintf($LANG->getLL('editThisColumn'),ereg_replace(':$','',trim($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol)))));
826 $theData[$fCol].='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
827 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.htmlspecialchars($iTitle).'" alt="" />'.
831 $theData[$fCol].=$this->addSortLink($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol,'<i>[|]</i>')),$fCol,$table);
838 * @hook renderListHeader: Allows to change the contents of columns/cells of the Web>List table headers
840 * @request Bernhard Kraft <krafbt@kraftb.at>
841 * @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.
843 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
844 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
845 $hookObject = &t3lib_div::getUserObj($classData);
846 if(!($hookObject instanceof localRecordList_actionsHook)) {
847 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567855);
849 $theData = $hookObject->renderListHeader($table, $currentIdList, $theData, $this);
853 // Create and return header table row:
854 return $this->addelement(1, $icon, $theData, ' class="c-headLine"', '');
862 /*********************************
864 * Rendering of various elements
866 *********************************/
869 * Creates the control panel for a single record in the listing.
871 * @param string The table
872 * @param array The record for which to make the control panel.
873 * @return string HTML table with the control panel (unless disabled)
875 function makeControl($table,$row) {
876 global $TCA, $LANG, $SOBE, $TYPO3_CONF_VARS;
878 if ($this->dontShowClipControlPanels) return '';
881 t3lib_div::loadTCA($table);
884 // If the listed table is 'pages' we have to request the permission settings for each page:
885 if ($table=='pages') {
886 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$row['uid']));
889 // This expresses the edit permissions for this particular element:
890 $permsEdit = ($table=='pages' && ($localCalcPerms&2)) || ($table!='pages' && ($this->calcPerms&16));
892 // "Show" link (only pages and tt_content elements)
893 if ($table=='pages' || $table=='tt_content') {
894 $params='&edit['.$table.']['.$row['uid'].']=edit';
895 $cells['view']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($table=='tt_content'?$this->id.'#'.$row['uid']:$row['uid'], $this->backPath)).'">'.
896 '<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="" />'.
898 } elseif(!$this->table) {
899 $cells['view'] = $this->spaceIcon;
902 // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
904 $params='&edit['.$table.']['.$row['uid'].']=edit';
905 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
906 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2'.(!$TCA[$table]['ctrl']['readOnly']?'':'_d').'.gif','width="11" height="12"').' title="'.$LANG->getLL('edit',1).'" alt="" />'.
908 } elseif(!$this->table) {
909 $cells['edit'] = $this->spaceIcon;
912 // "Move" wizard link for pages/tt_content elements:
913 if (($table=="tt_content" && $permsEdit) || ($table=='pages')) {
914 $cells['move']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'move_el.php?table='.$table.'&uid='.$row['uid'].'\');').'">'.
915 '<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="" />'.
917 } elseif(!$this->table) {
918 $cells['move'] = $this->spaceIcon;
921 // If the extended control panel is enabled OR if we are seeing a single table:
922 if ($SOBE->MOD_SETTINGS['bigControlPanel'] || $this->table) {
924 // "Info": (All records)
925 $cells['viewBig']='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$row['uid'].'\'); return false;').'">'.
926 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/zoom2.gif','width="12" height="12"').' title="'.$LANG->getLL('showInfo',1).'" alt="" />'.
929 // If the table is NOT a read-only table, then show these links:
930 if (!$TCA[$table]['ctrl']['readOnly']) {
932 // "Revert" link (history/undo)
933 $cells['history']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$row['uid']).'\',\'#latest\');').'">'.
934 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/history2.gif','width="13" height="12"').' title="'.$LANG->getLL('history',1).'" alt="" />'.
938 if (t3lib_extMgm::isLoaded('version')) {
939 $vers = t3lib_BEfunc::selectVersionsOfRecord($table, $row['uid'], 'uid', $GLOBALS['BE_USER']->workspace);
940 if (is_array($vers)) { // If table can be versionized.
941 if (count($vers)>1) {
942 $st = 'background-color: #FFFF00; font-weight: bold;';
943 $lab = count($vers)-1;
945 $st = 'background-color: #9999cc; font-weight: bold;';
949 $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" style="'.htmlspecialchars($st).'">'.
952 } elseif(!$this->table) {
953 $cells['version'] = '<span class="typo3-ctrl-versioning" style="font-weight: bold; visibility: hidden;">V</span>';
957 // "Edit Perms" link:
958 if ($table=='pages' && $GLOBALS['BE_USER']->check('modules','web_perm')) {
959 $cells['perms']='<a href="'.htmlspecialchars('mod/web/perm/index.php?id='.$row['uid'].'&return_id='.$row['uid'].'&edit=1').'">'.
960 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/perm.gif','width="7" height="12"').' title="'.$LANG->getLL('permissions',1).'" alt="" />'.
962 } elseif(!$this->table && $GLOBALS['BE_USER']->check('modules','web_perm')) {
963 $cells['perms'] = $this->spaceIcon;
966 // "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):
967 if ($TCA[$table]['ctrl']['sortby'] || $TCA[$table]['ctrl']['useColumnsForDefaultValues']) {
969 ($table!='pages' && ($this->calcPerms&16)) || // For NON-pages, must have permission to edit content on this parent page
970 ($table=='pages' && ($this->calcPerms&8)) // For pages, must have permission to create new pages here.
972 if ($this->showNewRecLink($table)) {
973 $params='&edit['.$table.']['.(-($row['_MOVE_PLH']?$row['_MOVE_PLH_uid']:$row['uid'])).']=new';
974 $cells['new']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
975 '<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="" />'.
979 } elseif(!$this->table) {
980 $cells['new'] = $this->spaceIcon;
984 if ($permsEdit && $TCA[$table]['ctrl']['sortby'] && !$this->sortField && !$this->searchLevels) {
985 if (isset($this->currentTable['prev'][$row['uid']])) { // Up
986 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prev'][$row['uid']];
987 $cells['moveUp']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
988 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_up.gif','width="11" height="10"').' title="'.$LANG->getLL('moveUp',1).'" alt="" />'.
991 $cells['moveUp'] = $this->spaceIcon;
993 if ($this->currentTable['next'][$row['uid']]) { // Down
994 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['next'][$row['uid']];
995 $cells['moveDown']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
996 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_down.gif','width="11" height="10"').' title="'.$LANG->getLL('moveDown',1).'" alt="" />'.
999 $cells['moveDown'] = $this->spaceIcon;
1001 } elseif(!$this->table) {
1002 $cells['moveUp'] = $this->spaceIcon;
1003 $cells['moveDown'] = $this->spaceIcon;
1006 // "Hide/Unhide" links:
1007 $hiddenField = $TCA[$table]['ctrl']['enablecolumns']['disabled'];
1008 if ($permsEdit && $hiddenField && $TCA[$table]['columns'][$hiddenField] && (!$TCA[$table]['columns'][$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$table.':'.$hiddenField))) {
1009 if ($row[$hiddenField]) {
1010 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=0';
1011 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1012 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_unhide.gif','width="11" height="10"').' title="'.$LANG->getLL('unHide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1015 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=1';
1016 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1017 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_hide.gif','width="11" height="10"').' title="'.$LANG->getLL('hide'.($table=='pages'?'Page':''),1).'" alt="" />'.
1020 } elseif(!$this->table) {
1021 $cells['hide'] = $this->spaceIcon;
1026 ($table=='pages' && ($localCalcPerms&4)) || ($table!='pages' && ($this->calcPerms&16))
1028 $params='&cmd['.$table.']['.$row['uid'].'][delete]=1';
1029 $cells['delete']='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$LANG->JScharCode($LANG->getLL('deleteWarning').t3lib_BEfunc::referenceCount($table,$row['uid'],' (There are %s reference(s) to this record!)')).')) {jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');} return false;').'">'.
1030 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$LANG->getLL('delete',1).'" alt="" />'.
1032 } elseif(!$this->table) {
1033 $cells['delete'] = $this->spaceIcon;
1036 // "Levels" links: Moving pages into new levels...
1037 if ($permsEdit && $table=='pages' && !$this->searchLevels) {
1039 // Up (Paste as the page right after the current parent page)
1040 if ($this->calcPerms&8) {
1041 $params='&cmd['.$table.']['.$row['uid'].'][move]='.-$this->id;
1042 $cells['moveLeft']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1043 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_left.gif','width="11" height="10"').' title="'.$LANG->getLL('prevLevel',1).'" alt="" />'.
1046 // Down (Paste as subpage to the page right above)
1047 if ($this->currentTable['prevUid'][$row['uid']]) {
1048 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$this->currentTable['prevUid'][$row['uid']]));
1049 if ($localCalcPerms&8) {
1050 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prevUid'][$row['uid']];
1051 $cells['moveRight']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'">'.
1052 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_right.gif','width="11" height="10"').' title="'.$LANG->getLL('nextLevel',1).'" alt="" />'.
1055 $cells['moveRight'] = $this->spaceIcon;
1058 $cells['moveRight'] = $this->spaceIcon;
1060 } elseif(!$this->table) {
1061 $cells['moveLeft'] = $this->spaceIcon;
1062 $cells['moveRight'] = $this->spaceIcon;
1067 // If the record is edit-locked by another user, we will show a little warning sign:
1068 if ($lockInfo=t3lib_BEfunc::isRecordLocked($table,$row['uid'])) {
1069 $cells['locked'] = '<a href="#" onclick="'.htmlspecialchars('alert('.$LANG->JScharCode($lockInfo['msg']).');return false;').'">'.
1070 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/recordlock_warning3.gif','width="17" height="12"').' title="'.htmlspecialchars($lockInfo['msg']).'" alt="" />'.
1075 * @hook recStatInfoHooks: Allows to insert HTML before record icons on various places
1077 * @request Kasper Skaarhoj <kasper2007@typo3.com>
1079 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) {
1081 $_params = array($table,$row['uid']);
1082 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) {
1083 $stat.=t3lib_div::callUserFunction($_funcRef,$_params,$this);
1085 $cells['stat'] = $stat;
1088 * @hook makeControl: Allows to change control icons of records in list-module
1090 * @request Bernhard Kraft <krafbt@kraftb.at>
1091 * @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 accesible by an index-key. The order of the icons is dependend on the order of those array entries.
1093 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1094 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1095 $hookObject = &t3lib_div::getUserObj($classData);
1096 if(!($hookObject instanceof localRecordList_actionsHook)) {
1097 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567840);
1099 $cells = $hookObject->makeControl($table, $row, $cells, $this);
1103 // Compile items into a DIV-element:
1105 <!-- CONTROL PANEL: '.$table.':'.$row['uid'].' -->
1106 <div class="typo3-DBctrl">'.implode('',$cells).'</div>';
1110 * Creates the clipboard panel for a single record in the listing.
1112 * @param string The table
1113 * @param array The record for which to make the clipboard panel.
1114 * @return string HTML table with the clipboard panel (unless disabled)
1116 function makeClip($table,$row) {
1117 global $TCA, $LANG, $TYPO3_CONF_VARS;
1119 // Return blank, if disabled:
1120 if ($this->dontShowClipControlPanels) return '';
1123 $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon;
1125 // Return blank, if disabled:
1126 // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel:
1127 if ($this->clipObj->current=='normal') { // For the "Normal" pad:
1129 // Show copy/cut icons:
1130 $isSel = (string)$this->clipObj->isSelected($table,$row['uid']);
1131 $cells['copy']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'.
1132 '<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="" />'.
1134 $cells['cut']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'.
1135 '<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="" />'.
1138 } else { // For the numeric clipboard pads (showing checkboxes where one can select elements on/off)
1140 // Setting name of the element in ->CBnames array:
1141 $n=$table.'|'.$row['uid'];
1142 $this->CBnames[]=$n;
1144 // Check if the current element is selected and if so, prepare to set the checkbox as selected:
1145 $checked = ($this->clipObj->isSelected($table,$row['uid'])?' checked="checked"':'');
1147 // If the "duplicateField" value is set then select all elements which are duplicates...
1148 if ($this->duplicateField && isset($row[$this->duplicateField])) {
1150 if (in_array($row[$this->duplicateField], $this->duplicateStack)) {
1151 $checked=' checked="checked"';
1153 $this->duplicateStack[] = $row[$this->duplicateField];
1156 // Adding the checkbox to the panel:
1157 $cells['select']='<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />';
1160 // Now, looking for selected elements from the current table:
1161 $elFromTable = $this->clipObj->elFromTable($table);
1162 if (count($elFromTable) && $TCA[$table]['ctrl']['sortby']) { // IF elements are found and they can be individually ordered, then add a "paste after" icon:
1163 $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,-$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'after',$elFromTable)).'">'.
1164 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteAfter',1).'" alt="" />'.
1168 // Now, looking for elements in general:
1169 $elFromTable = $this->clipObj->elFromTable('');
1170 if ($table=='pages' && count($elFromTable)) {
1171 $cells['pasteInto']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl('',$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'into',$elFromTable)).'">'.
1172 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteinto.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteInto',1).'" alt="" />'.
1177 * @hook makeClip: Allows to change clip-icons of records in list-module
1179 * @request Bernhard Kraft <krafbt@kraftb.at>
1180 * @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 accesible by an index-key. The order of the icons is dependend on the order of those array entries.
1182 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
1183 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
1184 $hookObject = &t3lib_div::getUserObj($classData);
1185 if(!($hookObject instanceof localRecordList_actionsHook)) {
1186 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567845);
1188 $cells = $hookObject->makeClip($table, $row, $cells, $this);
1192 // Compile items into a DIV-element:
1193 return ' <!-- CLIPBOARD PANEL: '.$table.':'.$row['uid'].' -->
1194 <div class="typo3-clipCtrl">'.implode('',$cells).'</div>';
1198 * Make reference count
1200 * @param string Table name
1201 * @param integer UID of record
1202 * @return string HTML-table
1204 function makeRef($table,$uid) {
1206 // Look up the path:
1207 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
1210 'ref_table='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_refindex').
1211 ' AND ref_uid='.intval($uid).
1215 // Compile information for title tag:
1217 if (is_array($rows)) {
1218 foreach($rows as $row) {
1219 $infoData[]=$row['tablename'].':'.$row['recuid'].':'.$row['field'];
1223 return count($infoData) ? '<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$uid.'\'); return false;').'" title="'.htmlspecialchars(t3lib_div::fixed_lgd(implode(' / ',$infoData),100)).'">'.count($infoData).'</a>' : '';
1227 * Creates the localization panel
1229 * @param string The table
1230 * @param array The record for which to make the localization panel.
1231 * @return array Array with key 0/1 with content for column 1 and 2
1233 function makeLocalizationPanel($table,$row) {
1241 $t8Tools = t3lib_div::makeInstance('t3lib_transl8tools');
1242 $translations = $t8Tools->translationInfo($table,$row['uid']);
1244 // Language title and icon:
1245 $out[0] = $this->languageFlag($row[$TCA[$table]['ctrl']['languageField']]);
1247 if (is_array($translations)) {
1249 // Traverse page translations and add icon for each language that does NOT yet exist:
1251 foreach($this->pageOverlays as $lUid_OnPage => $lsysRec) {
1252 if (!isset($translations['translations'][$lUid_OnPage]) && $GLOBALS['BE_USER']->checkLanguageAccess($lUid_OnPage)) {
1253 $href = $GLOBALS['TBE_TEMPLATE']->issueCommand(
1254 '&cmd['.$table.']['.$row['uid'].'][localize]='.$lUid_OnPage,
1255 $this->listURL().'&justLocalized='.rawurlencode($table.':'.$row['uid'].':'.$lUid_OnPage)
1258 $lC = ($this->languageIconTitles[$lUid_OnPage]['flagIcon'] ? '<img src="'.$this->languageIconTitles[$lUid_OnPage]['flagIcon'].'" class="absmiddle" alt="" />' : $this->languageIconTitles[$lUid_OnPage]['title']);
1259 $lC = '<a href="'.htmlspecialchars($href).'">'.$lC.'</a> ';
1265 if ($lNew) $out[1].= $lNew;
1267 $out[0] = ' '.$out[0];
1275 * Create the selector box for selecting fields to display from a table:
1277 * @param string Table name
1278 * @param boolean If true, form-fields will be wrapped around the table.
1279 * @return string HTML table with the selector box (name: displayFields['.$table.'][])
1281 function fieldSelectBox($table,$formFields=1) {
1285 t3lib_div::loadTCA($table);
1286 $formElements=array('','');
1288 $formElements=array('<form action="'.htmlspecialchars($this->listURL()).'" method="post">','</form>');
1291 // Load already selected fields, if any:
1292 $setFields=is_array($this->setFields[$table]) ? $this->setFields[$table] : array();
1294 // Request fields from table:
1295 $fields = $this->makeFieldList($table);
1297 // Add pseudo "control" fields
1302 $fields[]='_LOCALIZATION_';
1303 $fields[]='_CONTROL_';
1304 $fields[]='_CLIPBOARD_';
1306 // Create an option for each field:
1308 $opt[] = '<option value=""></option>';
1309 foreach($fields as $fN) {
1310 $fL = is_array($TCA[$table]['columns'][$fN]) ? ereg_replace(':$','',$LANG->sL($TCA[$table]['columns'][$fN]['label'])) : '['.$fN.']'; // Field label
1312 <option value="'.$fN.'"'.(in_array($fN,$setFields)?' selected="selected"':'').'>'.htmlspecialchars($fL).'</option>';
1315 // Compile the options into a multiple selector box:
1317 <select size="'.t3lib_div::intInRange(count($fields)+1,3,20).'" multiple="multiple" name="displayFields['.$table.'][]">'.implode('',$opt).'
1321 // Table with the field selector::
1323 '.$formElements[0].'
1326 Field selector for extended table view:
1328 <table border="0" cellpadding="0" cellspacing="0" class="bgColor4" id="typo3-dblist-fieldSelect">
1331 <td><input type="submit" name="search" value="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.setFields',1).'" /></td>
1348 /*********************************
1352 *********************************/
1355 * Creates a link around $string. The link contains an onclick action which submits the script with some clipboard action.
1356 * Currently, this is used for setting elements / delete elements.
1358 * @param string The HTML content to link (image/text)
1359 * @param string Table name
1360 * @param string Clipboard command (eg. "setCB" or "delete")
1361 * @param string Warning text, if any ("delete" uses this for confirmation)
1362 * @return string <a> tag wrapped link.
1364 function linkClipboardHeaderIcon($string,$table,$cmd,$warning='') {
1365 $onClickEvent = 'document.dblistForm.cmd.value=\''.$cmd.'\';document.dblistForm.cmd_table.value=\''.$table.'\';document.dblistForm.submit();';
1366 if ($warning) $onClickEvent = 'if (confirm('.$GLOBALS['LANG']->JScharCode($warning).')){'.$onClickEvent.'}';
1367 return '<a href="#" onclick="'.htmlspecialchars($onClickEvent.'return false;').'">'.$string.'</a>';
1371 * Returns true if a numeric clipboard pad is selected/active
1375 function clipNumPane() {
1376 return in_Array('_CLIPBOARD_',$this->fieldArray) && $this->clipObj->current!='normal';
1380 * Creates a sort-by link on the input string ($code).
1381 * It will automatically detect if sorting should be ascending or descending depending on $this->sortRev.
1382 * Also some fields will not be possible to sort (including if single-table-view is disabled).
1384 * @param string The string to link (text)
1385 * @param string The fieldname represented by the title ($code)
1386 * @param string Table name
1387 * @return string Linked $code variable
1389 function addSortLink($code,$field,$table) {
1391 // Certain circumstances just return string right away (no links):
1392 if ($field=='_CONTROL_' || $field=='_LOCALIZATION_' || $field=='_CLIPBOARD_' || $field=='_REF_' || $this->disableSingleTableView) return $code;
1394 // If "_PATH_" (showing record path) is selected, force sorting by pid field (will at least group the records!)
1395 if ($field=='_PATH_') $field=pid;
1397 // Create the sort link:
1398 $sortUrl = $this->listURL('',-1,'sortField,sortRev,table').'&table='.$table.'&sortField='.$field.'&sortRev='.($this->sortRev || ($this->sortField!=$field)?0:1);
1399 $sortArrow = ($this->sortField==$field?'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/red'.($this->sortRev?'up':'down').'.gif','width="7" height="4"').' alt="" />':'');
1401 // Return linked field:
1402 return '<a href="'.htmlspecialchars($sortUrl).'">'.$code.
1408 * Returns the path for a certain pid
1409 * The result is cached internally for the session, thus you can call this function as much as you like without performance problems.
1411 * @param integer The page id for which to get the path
1412 * @return string The path.
1414 function recPath($pid) {
1415 if (!isset($this->recPath_cache[$pid])) {
1416 $this->recPath_cache[$pid] = t3lib_BEfunc::getRecordPath($pid,$this->perms_clause,20);
1418 return $this->recPath_cache[$pid];
1422 * Returns true if a link for creating new records should be displayed for $table
1424 * @param string Table name
1425 * @return boolean Returns true if a link for creating new records should be displayed for $table
1426 * @see SC_db_new::showNewRecLink
1428 function showNewRecLink($table) {
1429 // No deny/allow tables are set:
1430 if (!count($this->allowedNewTables) && !count($this->deniedNewTables)) {
1432 // If table is not denied (which takes precedence over allowed tables):
1433 } elseif (!in_array($table, $this->deniedNewTables) && (!count($this->allowedNewTables) || in_array($table, $this->allowedNewTables))) {
1435 // If table is denied or allowed tables are set, but table is not part of:
1442 * 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.
1443 * Uses REQUEST_URI as value.
1447 function makeReturnUrl() {
1448 return '&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
1461 /************************************
1463 * CSV related functions
1465 ************************************/
1468 * Initializes internal csvLines array with the header of field names
1472 function initCSV() {
1475 $this->csvLines=array();
1477 // Getting header line with field names:
1479 foreach ($this->fieldArray as $fN) {
1480 if ($fN == '_CONTROL_' || $fn == '_CLIPBOARD_') {
1486 // Set the header + an empty row:
1487 $this->setCsvRow($csvRow);
1488 $this->csvLines[] = '';
1493 * Adds the content of input array $row to the CSV list:
1495 * @param array Record array, from which the values of fields found in $this->fieldArray will be listed in the CSV output.
1496 * @param string Table name
1499 function addToCSV($row,$table) {
1501 // Traversing fields, adding values from $row:
1503 foreach ($this->fieldArray as $fN) {
1506 $csvRow[] = $this->recPath($row['pid']);
1510 $csvRow[] = $this->makeRef($table, $row['uid']);
1513 // remove these columns from the CSV view
1520 $csvRow[] = $row[$fN];
1524 // Set the values in the CSV list
1525 $this->setCsvRow($csvRow);
1530 * Adds input row of values to the internal csvLines array as a CSV formatted line
1532 * @param array Array with values to be listed.
1535 function setCsvRow($csvRow) {
1536 $this->csvLines[] = t3lib_div::csvValues($csvRow);
1540 * Compiles the internal csvLines array to a csv-string and outputs it to the browser.
1541 * This function exits!
1543 * @param string Filename prefix:
1544 * @return void EXITS php execusion!
1546 function outputCSV($prefix) {
1548 // Setting filename:
1549 $filename=$prefix.'_'.date('dmy-Hi').'.csv';
1551 // Creating output header:
1552 $mimeType = 'application/octet-stream';
1553 Header('Content-Type: '.$mimeType);
1554 Header('Content-Disposition: attachment; filename='.$filename);
1556 // Printing the content of the CSV lines:
1557 echo implode(chr(13).chr(10),$this->csvLines);
1566 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']) {
1567 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']);