|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /************************************************************* 00003 * Copyright notice 00004 * 00005 * (c) 1999-2009 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 /** 00028 * Include file extending recordList which extended t3lib_recordList 00029 * Used specifically for the Web>List module (db_list.php) 00030 * 00031 * $Id: class.db_list_extra.inc 10315 2011-01-26 00:13:43Z baschny $ 00032 * Revised for TYPO3 3.6 December/2003 by Kasper Skårhøj 00033 * XHTML compliant 00034 * 00035 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00036 */ 00037 /** 00038 * [CLASS/FUNCTION INDEX of SCRIPT] 00039 * 00040 * 00041 * 00042 * 91: class localRecordList extends recordList 00043 * 123: function writeTop($row) 00044 * 304: function getTable($table,$id,$rowlist) 00045 * 559: function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0) 00046 * 648: function renderListHeader($table,$currentIdList) 00047 * 00048 * SECTION: Rendering of various elements 00049 * 796: function makeControl($table,$row) 00050 * 986: function makeClip($table,$row) 00051 * 1057: function makeRef($table,$uid) 00052 * 1086: function makeLocalizationPanel($table,$row) 00053 * 1148: function fieldSelectBox($table,$formFields=1) 00054 * 00055 * SECTION: Helper functions 00056 * 1231: function linkClipboardHeaderIcon($string,$table,$cmd,$warning='') 00057 * 1242: function clipNumPane() 00058 * 1256: function addSortLink($code,$field,$table) 00059 * 1281: function recPath($pid) 00060 * 1294: function showNewRecLink($table) 00061 * 1304: function makeReturnUrl() 00062 * 00063 * SECTION: CSV related functions 00064 * 1329: function initCSV() 00065 * 1352: function addToCSV($row,$table) 00066 * 1376: function setCsvRow($csvRow) 00067 * 1387: function outputCSV($prefix) 00068 * 00069 * TOTAL FUNCTIONS: 19 00070 * (This index is automatically created/updated by the extension "extdeveval") 00071 * 00072 */ 00073 00074 00075 00076 00077 00078 00079 00080 00081 00082 00083 /** 00084 * Class for rendering of Web>List module 00085 * 00086 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00087 * @package TYPO3 00088 * @subpackage core 00089 */ 00090 class localRecordList extends recordList { 00091 00092 // External: 00093 var $alternateBgColors=FALSE; // If true, table rows in the list will alternate in background colors (and have background colors at all!) 00094 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. 00095 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. 00096 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!). 00097 00098 var $dontShowClipControlPanels=FALSE; // If true, will disable the rendering of clipboard + control panels. 00099 var $showClipboard=FALSE; // If true, will show the clipboard in the field list. 00100 var $noControlPanels = FALSE; // If true, will DISABLE all control panels in lists. (Takes precedence) 00101 var $clickMenuEnabled = TRUE; // If true, clickmenus will be rendered 00102 00103 var $totalRowCount; // count of record rows in view 00104 00105 var $spaceIcon; // space icon used for alignment 00106 00107 // Internal: 00108 var $pageRow=array(); // Set to the page record (see writeTop()) 00109 00110 // Used to accumulate CSV lines for CSV export. 00111 protected $csvLines = array(); 00112 00113 var $csvOutput=FALSE; // If set, the listing is returned as CSV instead. 00114 00115 /** 00116 * Clipboard object 00117 * 00118 * @var t3lib_clipboard 00119 */ 00120 var $clipObj; 00121 var $CBnames=array(); // Tracking names of elements (for clipboard use) 00122 var $duplicateStack=array(); // Used to track which elements has duplicates and how many 00123 00124 /** 00125 * references of the current record 00126 * 00127 * @var array 00128 * 00129 * @deprecated since 4.4: Use getReferenceCount instead 00130 */ 00131 public $references; 00132 00133 /** 00134 * [$tablename][$uid] = number of references to this record 00135 * 00136 * @var array 00137 */ 00138 protected $referenceCount = array(); 00139 00140 var $translations; // Translations of the current record 00141 var $selFieldList; // select fields for the query which fetches the translations of the current record 00142 00143 public function __construct() { 00144 parent::__construct(); 00145 } 00146 00147 /** 00148 * Create the panel of buttons for submitting the form or otherwise perform operations. 00149 * 00150 * @return array all available buttons as an assoc. array 00151 */ 00152 public function getButtons() { 00153 global $LANG; 00154 00155 $buttons = array( 00156 'csh' => '', 00157 'view' => '', 00158 'edit' => '', 00159 'hide_unhide' => '', 00160 'move' => '', 00161 'new_record' => '', 00162 'paste' => '', 00163 'level_up' => '', 00164 'cache' => '', 00165 'reload' => '', 00166 'shortcut' => '', 00167 'back' => '', 00168 'csv' => '', 00169 'export' => '' 00170 ); 00171 00172 // Get users permissions for this page record: 00173 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms($this->pageRow); 00174 00175 // CSH 00176 if (!strlen($this->id)) { 00177 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_noId', $GLOBALS['BACK_PATH'], '', TRUE); 00178 } elseif(!$this->id) { 00179 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module_root', $GLOBALS['BACK_PATH'], '', TRUE); 00180 } else { 00181 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'list_module', $GLOBALS['BACK_PATH'], '', TRUE); 00182 } 00183 00184 if (isset($this->id)) { 00185 // View Exclude doktypes 254,255 Configuration: mod.web_list.noViewWithDokTypes = 254,255 00186 if (isset($GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'])) { 00187 $noViewDokTypes = t3lib_div::trimExplode(',', $GLOBALS['SOBE']->modTSconfig['properties']['noViewWithDokTypes'], true); 00188 } else { 00189 //default exclusion: doktype 254 (folder), 255 (recycler) 00190 $noViewDokTypes = array(t3lib_pageSelect::DOKTYPE_SYSFOLDER, t3lib_pageSelect::DOKTYPE_RECYCLER); 00191 } 00192 00193 if (!in_array($this->pageRow['doktype'], $noViewDokTypes)) { 00194 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewOnClick($this->id, $this->backPath, t3lib_BEfunc::BEgetRootLine($this->id))) . '" title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', TRUE) . '">' . 00195 t3lib_iconWorks::getSpriteIcon('actions-document-view') . 00196 '</a>'; 00197 } 00198 00199 // New record 00200 if (!$GLOBALS['SOBE']->modTSconfig['properties']['noCreateRecordsLink']) { 00201 $buttons['new_record'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'db_new.php?id=' . $this->id . '\');') . '" title="' . $LANG->getLL('newRecordGeneral', TRUE) . '">' . 00202 t3lib_iconWorks::getSpriteIcon('actions-document-new') . 00203 '</a>'; 00204 } 00205 00206 // If edit permissions are set (see class.t3lib_userauthgroup.php) 00207 if ($localCalcPerms&2 && !empty($this->id)) { 00208 00209 // Edit 00210 $params = '&edit[pages][' . $this->pageRow['uid'] . ']=edit'; 00211 $buttons['edit'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) . '" title="' . $LANG->getLL('editPage', TRUE) . '">' . 00212 t3lib_iconWorks::getSpriteIcon('actions-page-open') . 00213 '</a>'; 00214 // Unhide 00215 if ($this->pageRow['hidden']) { 00216 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=0'; 00217 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '" title="' . $LANG->getLL('unHidePage', TRUE) . '">' . 00218 t3lib_iconWorks::getSpriteIcon('actions-edit-unhide') . 00219 '</a>'; 00220 // Hide 00221 } else { 00222 $params = '&data[pages][' . $this->pageRow['uid'] . '][hidden]=1'; 00223 $buttons['hide_unhide'] = '<a href="#" onclick="' . htmlspecialchars('return jumpToUrl(\'' . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');') . '" title="' . $LANG->getLL('hidePage', TRUE) . '">'. 00224 t3lib_iconWorks::getSpriteIcon('actions-edit-hide') . 00225 '</a>'; 00226 } 00227 00228 // Move 00229 $buttons['move'] = '<a href="#" onclick="' . htmlspecialchars('return jumpExt(\'' . $this->backPath . 'move_el.php?table=pages&uid=' . $this->pageRow['uid'] . '\');') . '" title="' . $LANG->getLL('move_page', TRUE) . '">' . 00230 (($this->table == 'tt_content') ? t3lib_iconWorks::getSpriteIcon('actions-document-move') : t3lib_iconWorks::getSpriteIcon('actions-page-move')) . 00231 '</a>'; 00232 00233 // Up one level 00234 $buttons['level_up'] = '<a href="' . htmlspecialchars($this->listURL($this->pageRow['pid'])) . '" onclick="setHighlight(' . $this->pageRow['pid'] . ')" title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.upOneLevel', TRUE) . '">' . 00235 t3lib_iconWorks::getSpriteIcon('actions-view-go-up') . 00236 '</a>'; 00237 00238 } 00239 00240 00241 // Paste 00242 if (($localCalcPerms&8) || ($localCalcPerms&16)) { 00243 $elFromTable = $this->clipObj->elFromTable(''); 00244 if (count($elFromTable)) { 00245 $buttons['paste'] = '<a href="' . htmlspecialchars($this->clipObj->pasteUrl('', $this->id)) . '" onclick="' . htmlspecialchars('return ' . $this->clipObj->confirmMsg('pages', $this->pageRow, 'into', $elFromTable)) . '" title="' . $LANG->getLL('clip_paste', TRUE) . '">' . 00246 t3lib_iconWorks::getSpriteIcon('actions-document-paste-after') . 00247 '</a>'; 00248 } 00249 } 00250 00251 // Cache 00252 $buttons['cache'] = '<a href="' . htmlspecialchars($this->listURL() . '&clear_cache=1') . '" title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.clear_cache', TRUE) . '">' . 00253 t3lib_iconWorks::getSpriteIcon('actions-system-cache-clear') . 00254 '</a>'; 00255 00256 if ($this->table) { 00257 00258 // CSV 00259 $buttons['csv'] = '<a href="' . htmlspecialchars($this->listURL() . '&csv=1') . '" title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.csv', TRUE) . '">' . 00260 t3lib_iconWorks::getSpriteIcon('mimetypes-text-csv') . 00261 '</a>'; 00262 00263 // Export 00264 if (t3lib_extMgm::isLoaded('impexp')) { 00265 $url = $this->backPath . t3lib_extMgm::extRelPath('impexp') . 'app/index.php?tx_impexp[action]=export'; 00266 $buttons['export'] = '<a href="' . htmlspecialchars($url . '&tx_impexp[list][]=' . rawurlencode($this->table . ':' . $this->id)) . '" title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:rm.export', TRUE) . '">' . 00267 t3lib_iconWorks::getSpriteIcon('actions-document-export-t3d') . 00268 '</a>'; 00269 } 00270 00271 } 00272 00273 // Reload 00274 $buttons['reload'] = '<a href="' . htmlspecialchars($this->listURL()) . '" title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.reload', TRUE) . '">' . 00275 t3lib_iconWorks::getSpriteIcon('actions-system-refresh') . 00276 '</a>'; 00277 00278 // Shortcut 00279 if ($GLOBALS['BE_USER']->mayMakeShortcut()) { 00280 $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'); 00281 } 00282 00283 // Back 00284 if ($this->returnUrl) { 00285 $buttons['back'] = '<a href="' . htmlspecialchars(t3lib_div::linkThisUrl($this->returnUrl, array('id' => $this->id))) . '" class="typo3-goBack" title="' . $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.goBack', TRUE) . '">' . 00286 t3lib_iconWorks::getSpriteIcon('actions-view-go-back') . 00287 '</a>'; 00288 } 00289 } 00290 00291 return $buttons; 00292 } 00293 00294 /** 00295 * Creates the listing of records from a single table 00296 * 00297 * @param string Table name 00298 * @param integer Page id 00299 * @param string List of fields to show in the listing. Pseudo fields will be added including the record header. 00300 * @return string HTML table with the listing for the record. 00301 */ 00302 function getTable($table,$id,$rowlist) { 00303 global $TCA, $TYPO3_CONF_VARS; 00304 00305 // Loading all TCA details for this table: 00306 t3lib_div::loadTCA($table); 00307 00308 // Init 00309 $addWhere = ''; 00310 $titleCol = $TCA[$table]['ctrl']['label']; 00311 $thumbsCol = $TCA[$table]['ctrl']['thumbnail']; 00312 $l10nEnabled = $TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField'] && !$TCA[$table]['ctrl']['transOrigPointerTable']; 00313 $tableCollapsed = (!$this->tablesCollapsed[$table]) ? false : true; 00314 00315 // prepare space icon 00316 $this->spaceIcon = t3lib_iconWorks::getSpriteIcon('empty-empty', array('style' => 'background-position: 0 10px;')); 00317 00318 // Cleaning rowlist for duplicates and place the $titleCol as the first column always! 00319 $this->fieldArray=array(); 00320 // title Column 00321 $this->fieldArray[] = $titleCol; // Add title column 00322 // Control-Panel 00323 if (!t3lib_div::inList($rowlist,'_CONTROL_')) { 00324 $this->fieldArray[] = '_CONTROL_'; 00325 $this->fieldArray[] = '_AFTERCONTROL_'; 00326 } 00327 // Clipboard 00328 if ($this->showClipboard) { 00329 $this->fieldArray[] = '_CLIPBOARD_'; 00330 } 00331 // Ref 00332 if (!$this->dontShowClipControlPanels) { 00333 $this->fieldArray[]='_REF_'; 00334 $this->fieldArray[]='_AFTERREF_'; 00335 } 00336 // Path 00337 if ($this->searchLevels) { 00338 $this->fieldArray[]='_PATH_'; 00339 } 00340 // Localization 00341 if ($this->localizationView && $l10nEnabled) { 00342 $this->fieldArray[] = '_LOCALIZATION_'; 00343 $this->fieldArray[] = '_LOCALIZATION_b'; 00344 $addWhere.=' AND ( 00345 '.$TCA[$table]['ctrl']['languageField'].'<=0 00346 OR 00347 '.$TCA[$table]['ctrl']['transOrigPointerField'].' = 0 00348 )'; 00349 } 00350 // Cleaning up: 00351 $this->fieldArray=array_unique(array_merge($this->fieldArray,t3lib_div::trimExplode(',',$rowlist,1))); 00352 if ($this->noControlPanels) { 00353 $tempArray = array_flip($this->fieldArray); 00354 unset($tempArray['_CONTROL_']); 00355 unset($tempArray['_CLIPBOARD_']); 00356 $this->fieldArray = array_keys($tempArray); 00357 } 00358 00359 // Creating the list of fields to include in the SQL query: 00360 $selectFields = $this->fieldArray; 00361 $selectFields[] = 'uid'; 00362 $selectFields[] = 'pid'; 00363 if ($thumbsCol) $selectFields[] = $thumbsCol; // adding column for thumbnails 00364 if ($table=='pages') { 00365 if (t3lib_extMgm::isLoaded('cms')) { 00366 $selectFields[] = 'module'; 00367 $selectFields[] = 'extendToSubpages'; 00368 $selectFields[] = 'nav_hide'; 00369 } 00370 $selectFields[] = 'doktype'; 00371 } 00372 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) { 00373 $selectFields = array_merge($selectFields,$TCA[$table]['ctrl']['enablecolumns']); 00374 } 00375 if ($TCA[$table]['ctrl']['type']) { 00376 $selectFields[] = $TCA[$table]['ctrl']['type']; 00377 } 00378 if ($TCA[$table]['ctrl']['typeicon_column']) { 00379 $selectFields[] = $TCA[$table]['ctrl']['typeicon_column']; 00380 } 00381 if ($TCA[$table]['ctrl']['versioningWS']) { 00382 $selectFields[] = 't3ver_id'; 00383 $selectFields[] = 't3ver_state'; 00384 $selectFields[] = 't3ver_wsid'; 00385 $selectFields[] = 't3ver_swapmode'; // Filtered out when pages in makeFieldList() 00386 } 00387 if ($l10nEnabled) { 00388 $selectFields[] = $TCA[$table]['ctrl']['languageField']; 00389 $selectFields[] = $TCA[$table]['ctrl']['transOrigPointerField']; 00390 } 00391 if ($TCA[$table]['ctrl']['label_alt']) { 00392 $selectFields = array_merge($selectFields,t3lib_div::trimExplode(',',$TCA[$table]['ctrl']['label_alt'],1)); 00393 } 00394 $selectFields = array_unique($selectFields); // Unique list! 00395 $selectFields = array_intersect($selectFields,$this->makeFieldList($table,1)); // Making sure that the fields in the field-list ARE in the field-list from TCA! 00396 $selFieldList = implode(',',$selectFields); // implode it into a list of fields for the SQL-statement. 00397 $this->selFieldList = $selFieldList; 00398 00399 /** 00400 * @hook DB-List getTable 00401 * @date 2007-11-16 00402 * @request Malte Jansen <mail@maltejansen.de> 00403 */ 00404 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) { 00405 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) { 00406 $hookObject = t3lib_div::getUserObj($classData); 00407 00408 if(!($hookObject instanceof t3lib_localRecordListGetTableHook)) { 00409 throw new UnexpectedValueException('$hookObject must implement interface t3lib_localRecordListGetTableHook', 1195114460); 00410 } 00411 00412 $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this); 00413 } 00414 } 00415 00416 // Create the SQL query for selecting the elements in the listing: 00417 if ($this->csvOutput) { // do not do paging when outputting as CSV 00418 $this->iLimit = 0; 00419 } 00420 00421 if ($this->firstElementNumber > 2 && $this->iLimit > 0) { 00422 // Get the two previous rows for sorting if displaying page > 1 00423 $this->firstElementNumber = $this->firstElementNumber - 2; 00424 $this->iLimit = $this->iLimit + 2; 00425 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc) 00426 $this->firstElementNumber = $this->firstElementNumber + 2; 00427 $this->iLimit = $this->iLimit - 2; 00428 } else { 00429 $queryParts = $this->makeQueryArray($table, $id,$addWhere,$selFieldList); // (API function from class.db_list.inc) 00430 } 00431 00432 $this->setTotalItems($queryParts); // Finding the total amount of records on the page (API function from class.db_list.inc) 00433 00434 // Init: 00435 $dbCount = 0; 00436 $out = ''; 00437 $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table; 00438 00439 // If the count query returned any number of records, we perform the real query, selecting records. 00440 if ($this->totalItems) { 00441 // Fetch records only if not in single table mode or if in multi table mode and not collapsed 00442 if ($listOnlyInSingleTableMode || (!$this->table && $tableCollapsed)) { 00443 $dbCount = $this->totalItems; 00444 } else { 00445 // set the showLimit to the number of records when outputting as CSV 00446 if ($this->csvOutput) { 00447 $this->showLimit = $this->totalItems; 00448 $this->iLimit = $this->totalItems; 00449 } 00450 $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts); 00451 $dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result); 00452 } 00453 } 00454 00455 // If any records was selected, render the list: 00456 if ($dbCount) { 00457 00458 // Half line is drawn between tables: 00459 if (!$listOnlyInSingleTableMode) { 00460 $theData = Array(); 00461 if (!$this->table && !$rowlist) { 00462 $theData[$titleCol] = '<img src="clear.gif" width="'.($GLOBALS['SOBE']->MOD_SETTINGS['bigControlPanel']?'230':'350').'" height="1" alt="" />'; 00463 if (in_array('_CONTROL_',$this->fieldArray)) $theData['_CONTROL_']=''; 00464 if (in_array('_CLIPBOARD_',$this->fieldArray)) $theData['_CLIPBOARD_']=''; 00465 } 00466 $out.=$this->addelement(0,'',$theData,'class="c-table-row-spacer"',$this->leftMargin); 00467 } 00468 00469 // Header line is drawn 00470 $theData = Array(); 00471 if ($this->disableSingleTableView) { 00472 $theData[$titleCol] = '<span class="c-table">' . t3lib_BEfunc::wrapInHelp($table, '', $GLOBALS['LANG']->sL($TCA[$table]['ctrl']['title'], TRUE)) . '</span> ('.$this->totalItems.')'; 00473 } else { 00474 $theData[$titleCol] = $this->linkWrapTable($table, '<span class="c-table">' . $GLOBALS['LANG']->sL($TCA[$table]['ctrl']['title'], TRUE) . '</span> (' . $this->totalItems . ') ' . 00475 ($this->table ? t3lib_iconWorks::getSpriteIcon('actions-view-table-collapse', array('title' => $GLOBALS['LANG']->getLL('contractView', TRUE))) : t3lib_iconWorks::getSpriteIcon('actions-view-table-expand', array('title' => $GLOBALS['LANG']->getLL('expandView', TRUE)))) 00476 ); 00477 } 00478 00479 if ($listOnlyInSingleTableMode) { 00480 $out.=' 00481 <tr> 00482 <td class="t3-row-header" style="width:95%;">' . t3lib_BEfunc::wrapInHelp($table, '', $theData[$titleCol]) . '</td> 00483 </tr>'; 00484 } else { 00485 // Render collapse button if in multi table mode 00486 $collapseIcon = ''; 00487 if (!$this->table) { 00488 $collapseIcon = '<a href="' . htmlspecialchars($this->listURL() . '&collapse[' . $table . ']=' . ($tableCollapsed ? '0' : '1')) . '" title="' . ($tableCollapsed ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.expandTable', TRUE) : $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.collapseTable', TRUE)) . '">' . 00489 ($tableCollapsed ? t3lib_iconWorks::getSpriteIcon('actions-view-list-expand', array('class' => 'collapseIcon')) : t3lib_iconWorks::getSpriteIcon('actions-view-list-collapse', array('class' => 'collapseIcon'))) . 00490 '</a>'; 00491 } 00492 $out .= $this->addElement(1, $collapseIcon, $theData, ' class="t3-row-header"', ''); 00493 } 00494 00495 // Render table rows only if in multi table view and not collapsed or if in single table view 00496 if (!$listOnlyInSingleTableMode && (!$tableCollapsed || $this->table)) { 00497 // Fixing a order table for sortby tables 00498 $this->currentTable = array(); 00499 $currentIdList = array(); 00500 $doSort = ($TCA[$table]['ctrl']['sortby'] && !$this->sortField); 00501 00502 $prevUid = 0; 00503 $prevPrevUid = 0; 00504 00505 // Get first two rows and initialize prevPrevUid and prevUid if on page > 1 00506 if ($this->firstElementNumber > 2 && $this->iLimit > 0) { 00507 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result); 00508 $prevPrevUid = -(int) $row['uid']; 00509 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result); 00510 $prevUid = $row['uid']; 00511 } 00512 00513 $accRows = array(); // Accumulate rows here 00514 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { 00515 00516 // In offline workspace, look for alternative record: 00517 t3lib_BEfunc::workspaceOL($table, $row, $GLOBALS['BE_USER']->workspace, TRUE); 00518 00519 if (is_array($row)) { 00520 $accRows[] = $row; 00521 $currentIdList[] = $row['uid']; 00522 if ($doSort) { 00523 if ($prevUid) { 00524 $this->currentTable['prev'][$row['uid']] = $prevPrevUid; 00525 $this->currentTable['next'][$prevUid] = '-'.$row['uid']; 00526 $this->currentTable['prevUid'][$row['uid']] = $prevUid; 00527 } 00528 $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid']; 00529 $prevUid=$row['uid']; 00530 } 00531 } 00532 } 00533 $GLOBALS['TYPO3_DB']->sql_free_result($result); 00534 00535 $this->totalRowCount = count($accRows); 00536 00537 // CSV initiated 00538 if ($this->csvOutput) $this->initCSV(); 00539 00540 // Render items: 00541 $this->CBnames=array(); 00542 $this->duplicateStack=array(); 00543 $this->eCounter=$this->firstElementNumber; 00544 00545 $iOut = ''; 00546 $cc = 0; 00547 00548 foreach($accRows as $row) { 00549 // Render item row if counter < limit 00550 if ($cc < $this->iLimit) { 00551 $cc++; 00552 $this->translations = FALSE; 00553 $iOut.= $this->renderListRow($table,$row,$cc,$titleCol,$thumbsCol); 00554 00555 // 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: 00556 if ($this->localizationView && $l10nEnabled) { 00557 // For each available translation, render the record: 00558 if (is_array($this->translations)) { 00559 foreach ($this->translations as $lRow) { 00560 // $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 00561 if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) { 00562 $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); 00563 $lRow = is_array($tmpRow)?$tmpRow:$lRow; 00564 } 00565 // In offline workspace, look for alternative record: 00566 t3lib_BEfunc::workspaceOL($table, $lRow, $GLOBALS['BE_USER']->workspace, true); 00567 if (is_array($lRow) && $GLOBALS['BE_USER']->checkLanguageAccess($lRow[$TCA[$table]['ctrl']['languageField']])) { 00568 $currentIdList[] = $lRow['uid']; 00569 $iOut.=$this->renderListRow($table,$lRow,$cc,$titleCol,$thumbsCol,18); 00570 } 00571 } 00572 } 00573 } 00574 } 00575 00576 // Counter of total rows incremented: 00577 $this->eCounter++; 00578 } 00579 00580 // Record navigation is added to the beginning and end of the table if in single table mode 00581 if ($this->table) { 00582 $iOut = $this->renderListNavigation('top') . $iOut . $this->renderListNavigation('bottom'); 00583 } else { 00584 // show that there are more records than shown 00585 if ($this->totalItems > $this->itemsLimitPerTable) { 00586 $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems; 00587 $hasMore = ($this->totalItems > $this->itemsLimitSingleTable); 00588 $iOut .= '<tr><td colspan="' . count($this->fieldArray) . '" style="padding:5px;"> 00589 <a href="'.htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '">' . 00590 '<img' . t3lib_iconWorks::skinImg($this->backPath,'gfx/pildown.gif', 'width="14" height="14"') .' alt="" />'. 00591 ' <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a> 00592 </td></tr>'; 00593 } 00594 00595 } 00596 00597 // The header row for the table is now created: 00598 $out .= $this->renderListHeader($table,$currentIdList); 00599 } 00600 00601 // The list of records is added after the header: 00602 $out .= $iOut; 00603 unset($iOut); 00604 00605 // ... and it is all wrapped in a table: 00606 $out=' 00607 00608 00609 00610 <!-- 00611 DB listing of elements: "'.htmlspecialchars($table).'" 00612 --> 00613 <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist'.($listOnlyInSingleTableMode?' typo3-dblist-overview':'').'"> 00614 '.$out.' 00615 </table>'; 00616 00617 // Output csv if... 00618 if ($this->csvOutput) $this->outputCSV($table); // This ends the page with exit. 00619 } 00620 00621 // Return content: 00622 return $out; 00623 } 00624 00625 /** 00626 * Rendering a single row for the list 00627 * 00628 * @param string Table name 00629 * @param array Current record 00630 * @param integer Counter, counting for each time an element is rendered (used for alternating colors) 00631 * @param string Table field (column) where header value is found 00632 * @param string Table field (column) where (possible) thumbnails can be found 00633 * @param integer Indent from left. 00634 * @return string Table row for the element 00635 * @access private 00636 * @see getTable() 00637 */ 00638 function renderListRow($table,$row,$cc,$titleCol,$thumbsCol,$indent=0) { 00639 $iOut = ''; 00640 00641 if (strlen($this->searchString)) { // If in search mode, make sure the preview will show the correct page 00642 $id_orig = $this->id; 00643 $this->id = $row['pid']; 00644 } 00645 00646 if (is_array($row)) { 00647 // add special classes for first and last row 00648 $rowSpecial = ''; 00649 if ($cc == 1 && $indent == 0) { 00650 $rowSpecial .= ' firstcol'; 00651 } 00652 if ($cc == $this->totalRowCount || $cc == $this->iLimit) { 00653 $rowSpecial .= ' lastcol'; 00654 } 00655 00656 // Background color, if any: 00657 if ($this->alternateBgColors) { 00658 $row_bgColor = ($cc%2) ? ' class="db_list_normal'.$rowSpecial.'"' : ' class="db_list_alt'.$rowSpecial.'"'; 00659 } else { 00660 $row_bgColor = ' class="db_list_normal'.$rowSpecial.'"'; 00661 } 00662 // Overriding with versions background color if any: 00663 $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor; 00664 00665 // Incr. counter. 00666 $this->counter++; 00667 00668 // The icon with link 00669 $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table); 00670 $iconImg = t3lib_iconWorks::getSpriteIconForRecord($table, $row, array('title' => htmlspecialchars($alttext), 'style' => ($indent ? ' margin-left: ' . $indent . 'px;' : ''))); 00671 00672 00673 $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg; 00674 00675 // Preparing and getting the data-array 00676 $theData = Array(); 00677 foreach($this->fieldArray as $fCol) { 00678 if ($fCol==$titleCol) { 00679 $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE); 00680 // If the record is edit-locked by another user, we will show a little warning sign: 00681 if (($lockInfo = t3lib_BEfunc::isRecordLocked($table, $row['uid']))) { 00682 $warning = '<a href="#" onclick="' . htmlspecialchars('alert(' . $GLOBALS['LANG']->JScharCode($lockInfo['msg']) . '); return false;') . '" title="' . htmlspecialchars($lockInfo['msg']) . '">' . 00683 t3lib_iconWorks::getSpriteIcon('status-warning-in-use') . 00684 '</a>'; 00685 } 00686 $theData[$fCol] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row); 00687 00688 // Render thumbsnails if a thumbnail column exists and there is content in it: 00689 if ($this->thumbs && trim($row[$thumbsCol])) { 00690 $theData[$fCol] .= '<br />' . $this->thumbCode($row,$table,$thumbsCol); 00691 } 00692 00693 $localizationMarkerClass = ''; 00694 if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) 00695 && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0 00696 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) { 00697 // it's a translated record with a language parent 00698 $localizationMarkerClass = ' localization'; 00699 } 00700 } elseif ($fCol == 'pid') { 00701 $theData[$fCol]=$row[$fCol]; 00702 } elseif ($fCol == '_PATH_') { 00703 $theData[$fCol]=$this->recPath($row['pid']); 00704 } elseif ($fCol == '_REF_') { 00705 $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']); 00706 } elseif ($fCol == '_CONTROL_') { 00707 $theData[$fCol]=$this->makeControl($table,$row); 00708 } elseif ($fCol == '_AFTERCONTROL_' || $fCol == '_AFTERREF_') { 00709 $theData[$fCol] = ' '; 00710 } elseif ($fCol == '_CLIPBOARD_') { 00711 $theData[$fCol]=$this->makeClip($table,$row); 00712 } elseif ($fCol == '_LOCALIZATION_') { 00713 list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row); 00714 $theData[$fCol] = $lC1; 00715 $theData[$fCol.'b'] = $lC2; 00716 } elseif ($fCol == '_LOCALIZATION_b') { 00717 // Do nothing, has been done above. 00718 } else { 00719 $tmpProc = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']); 00720 $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]); 00721 if ($this->csvOutput) { 00722 $row[$fCol] = t3lib_BEfunc::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']); 00723 } 00724 } 00725 } 00726 00727 if (strlen($this->searchString)) { // Reset the ID if it was overwritten 00728 $this->id = $id_orig; 00729 } 00730 00731 // Add row to CSV list: 00732 if ($this->csvOutput) { 00733 $this->addToCSV($row,$table); 00734 } 00735 00736 // Add classes to table cells 00737 $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass; 00738 if (!$this->dontShowClipControlPanels) { 00739 $this->addElement_tdCssClass['_CONTROL_'] = 'col-control'; 00740 $this->addElement_tdCssClass['_AFTERCONTROL_'] = 'col-control-space'; 00741 $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard'; 00742 } 00743 $this->addElement_tdCssClass['_PATH_'] = 'col-path'; 00744 $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa'; 00745 $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb'; 00746 00747 // Create element in table cells: 00748 $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor); 00749 00750 // Finally, return table row element: 00751 return $iOut; 00752 } 00753 } 00754 00755 /** 00756 * Write sys_refindex entries for current record to $this->references 00757 * 00758 * @param string Table name 00759 * @param integer Uid of current record 00760 * @return void 00761 * 00762 * @deprecated since 4.4, will be removed in TYPO3 4.6 - Use getReferenceCount instead 00763 */ 00764 function setReferences($table, $uid) { 00765 t3lib_div::logDeprecatedFunction(); 00766 00767 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( 00768 'tablename, recuid, field', 00769 'sys_refindex', 00770 'ref_table='.$GLOBALS['TYPO3_DB']->fullQuoteStr($table,'sys_refindex'). 00771 ' AND ref_uid='.intval($uid). 00772 ' AND deleted=0' 00773 ); 00774 $this->references = $rows; 00775 } 00776 00777 /** 00778 * Gets the number of records referencing the record with the UID $uid in 00779 * the table $tableName. 00780 * 00781 * @param string $tableName 00782 * table name of the referenced record, must not be empty 00783 * @param integer $uid 00784 * UID of the referenced record, must be > 0 00785 * 00786 * @return integer the number of references to record $uid in table 00787 * $tableName, will be >= 0 00788 */ 00789 protected function getReferenceCount($tableName, $uid) { 00790 if (!isset($this->referenceCount[$tableName][$uid])) { 00791 $numberOfReferences = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( 00792 '*', 00793 'sys_refindex', 00794 'ref_table = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr( 00795 $tableName, 'sys_refindex' 00796 ) . 00797 ' AND ref_uid = ' . $uid . 00798 ' AND deleted = 0' 00799 ); 00800 00801 $this->referenceCount[$tableName][$uid] = $numberOfReferences; 00802 } 00803 00804 return $this->referenceCount[$tableName][$uid]; 00805 } 00806 00807 /** 00808 * Rendering the header row for a table 00809 * 00810 * @param string Table name 00811 * @param array Array of the currently displayed uids of the table 00812 * @return string Header table row 00813 * @access private 00814 * @see getTable() 00815 */ 00816 function renderListHeader($table, $currentIdList) { 00817 global $TCA, $LANG, $TYPO3_CONF_VARS; 00818 00819 // Init: 00820 $theData = Array(); 00821 00822 // Traverse the fields: 00823 foreach($this->fieldArray as $fCol) { 00824 00825 // Calculate users permissions to edit records in the table: 00826 $permsEdit = $this->calcPerms & ($table=='pages'?2:16); 00827 00828 switch((string)$fCol) { 00829 case '_PATH_': // Path 00830 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._PATH_',1).']</i>'; 00831 break; 00832 case '_REF_': // References 00833 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_mod_file_list.xml:c__REF_',1).']</i>'; 00834 break; 00835 case '_LOCALIZATION_': // Path 00836 $theData[$fCol] = '<i>['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels._LOCALIZATION_',1).']</i>'; 00837 break; 00838 case '_LOCALIZATION_b': // Path 00839 $theData[$fCol] = $LANG->getLL('Localize',1); 00840 break; 00841 case '_CLIPBOARD_': // Clipboard: 00842 $cells=array(); 00843 00844 // If there are elements on the clipboard for this table, then display the "paste into" icon: 00845 $elFromTable = $this->clipObj->elFromTable($table); 00846 if (count($elFromTable)) { 00847 $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,$this->id)).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg('pages',$this->pageRow,'into',$elFromTable)).'" title="' . $LANG->getLL('clip_paste', TRUE) . '">' . 00848 t3lib_iconWorks::getSpriteIcon('actions-document-paste-after') . 00849 '</a>'; 00850 } 00851 00852 // If the numeric clipboard pads are enabled, display the control icons for that: 00853 if ($this->clipObj->current!='normal') { 00854 00855 // The "select" link: 00856 $cells['copyMarked']=$this->linkClipboardHeaderIcon(t3lib_iconWorks::getSpriteIcon('actions-edit-copy', array('title' => $LANG->getLL('clip_selectMarked', TRUE))), $table, 'setCB'); 00857 00858 // The "edit marked" link: 00859 $editIdList = implode(',',$currentIdList); 00860 $editIdList = "'+editList('".$table."','".$editIdList."')+'"; 00861 $params='&edit['.$table.']['.$editIdList.']=edit&disHelp=1'; 00862 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'" title="' . $LANG->getLL('clip_editMarked', TRUE) . '">' . 00863 t3lib_iconWorks::getSpriteIcon('actions-document-open') . 00864 '</a>'; 00865 00866 // The "Delete marked" link: 00867 $cells['delete']=$this->linkClipboardHeaderIcon(t3lib_iconWorks::getSpriteIcon('actions-edit-delete', array('title' => $LANG->getLL('clip_deleteMarked', TRUE))), $table,'delete',sprintf($LANG->getLL('clip_deleteMarkedWarning'), $LANG->sL($TCA[$table]['ctrl']['title']))); 00868 00869 // The "Select all" link: 00870 $cells['markAll'] = '<a class="cbcCheckAll" rel="" href="#" onclick="' . htmlspecialchars('checkOffCB(\'' . implode(',', $this->CBnames) . '\', this); return false;') . '" title="' . $LANG->getLL('clip_markRecords', TRUE) . '">' . 00871 t3lib_iconWorks::getSpriteIcon('actions-document-select') . 00872 '</a>'; 00873 } else { 00874 $cells['empty']=''; 00875 } 00876 /** 00877 * @hook renderListHeaderActions: Allows to change the clipboard icons of the Web>List table headers 00878 * @date 2007-11-20 00879 * @request Bernhard Kraft <krafbt@kraftb.at> 00880 * @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. 00881 */ 00882 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) { 00883 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) { 00884 $hookObject = t3lib_div::getUserObj($classData); 00885 if(!($hookObject instanceof localRecordList_actionsHook)) { 00886 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567850); 00887 } 00888 $cells = $hookObject->renderListHeaderActions($table, $currentIdList, $cells, $this); 00889 } 00890 } 00891 $theData[$fCol]=implode('',$cells); 00892 break; 00893 case '_CONTROL_': // Control panel: 00894 if (!$TCA[$table]['ctrl']['readOnly']) { 00895 00896 // If new records can be created on this page, add links: 00897 if ($this->calcPerms&($table=='pages'?8:16) && $this->showNewRecLink($table)) { 00898 if ($table=="tt_content" && $this->newWizards) { 00899 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead: 00900 $tmpTSc = t3lib_BEfunc::getModTSconfig($this->pageinfo['uid'],'mod.web_list'); 00901 $tmpTSc = $tmpTSc ['properties']['newContentWiz.']['overrideWithExtension']; 00902 $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'; 00903 00904 $icon = '<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$newContentWizScriptPath.'?id='.$this->id.'\');').'" title="' . $LANG->getLL('new', TRUE) . '">'. 00905 ($table == 'pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) . 00906 '</a>'; 00907 } elseif ($table=='pages' && $this->newWizards) { 00908 $icon = '<a href="'.htmlspecialchars($this->backPath.'db_new.php?id='.$this->id.'&pagesOnly=1&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'" title="'.$LANG->getLL('new', TRUE).'">'. 00909 ($table=='pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) . 00910 '</a>'; 00911 00912 } else { 00913 $params = '&edit['.$table.']['.$this->id.']=new'; 00914 if ($table == 'pages_language_overlay') { 00915 $params .= '&overrideVals[pages_language_overlay][doktype]=' . (int) $this->pageRow['doktype']; 00916 } 00917 $icon = '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'" title="'.$LANG->getLL('new', TRUE).'">'. 00918 ($table=='pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) . 00919 '</a>'; 00920 } 00921 } 00922 00923 // If the table can be edited, add link for editing ALL SHOWN fields for all listed records: 00924 if ($permsEdit && $this->table && is_array($currentIdList)) { 00925 $editIdList = implode(',',$currentIdList); 00926 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'"; 00927 $params = '&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.implode(',',$this->fieldArray).'&disHelp=1'; 00928 $icon .= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'" title="'.$LANG->getLL('editShownColumns', TRUE) . '">'. 00929 t3lib_iconWorks::getSpriteIcon('actions-document-open') . 00930 '</a>'; 00931 } 00932 // add an empty entry, so column count fits again after moving this into $icon 00933 $theData[$fCol] = ' '; 00934 } 00935 break; 00936 case '_AFTERCONTROL_': // space column 00937 case '_AFTERREF_': // space column 00938 $theData[$fCol] = ' '; 00939 break; 00940 default: // Regular fields header: 00941 $theData[$fCol]=''; 00942 if ($this->table && is_array($currentIdList)) { 00943 00944 // If the numeric clipboard pads are selected, show duplicate sorting link: 00945 if ($this->clipNumPane()) { 00946 $theData[$fCol].='<a href="'.htmlspecialchars($this->listURL('',-1).'&duplicateField='.$fCol).'" title="'.$LANG->getLL('clip_duplicates', TRUE) . '">'. 00947 t3lib_iconWorks::getSpriteIcon('actions-document-duplicates-select') . 00948 '</a>'; 00949 } 00950 00951 // If the table can be edited, add link for editing THIS field for all listed records: 00952 if (!$TCA[$table]['ctrl']['readOnly'] && $permsEdit && $TCA[$table]['columns'][$fCol]) { 00953 $editIdList = implode(',',$currentIdList); 00954 if ($this->clipNumPane()) $editIdList = "'+editList('".$table."','".$editIdList."')+'"; 00955 $params='&edit['.$table.']['.$editIdList.']=edit&columnsOnly='.$fCol.'&disHelp=1'; 00956 $iTitle = sprintf($LANG->getLL('editThisColumn'),rtrim(trim($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol))),':')); 00957 $theData[$fCol].='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'" title="'.htmlspecialchars($iTitle).'">'. 00958 t3lib_iconWorks::getSpriteIcon('actions-document-open') . 00959 '</a>'; 00960 } 00961 } 00962 $theData[$fCol].=$this->addSortLink($LANG->sL(t3lib_BEfunc::getItemLabel($table,$fCol,'<i>[|]</i>')),$fCol,$table); 00963 break; 00964 } 00965 00966 } 00967 00968 /** 00969 * @hook renderListHeader: Allows to change the contents of columns/cells of the Web>List table headers 00970 * @date 2007-11-20 00971 * @request Bernhard Kraft <krafbt@kraftb.at> 00972 * @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. 00973 */ 00974 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) { 00975 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) { 00976 $hookObject = t3lib_div::getUserObj($classData); 00977 if(!($hookObject instanceof localRecordList_actionsHook)) { 00978 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567855); 00979 } 00980 $theData = $hookObject->renderListHeader($table, $currentIdList, $theData, $this); 00981 } 00982 } 00983 00984 // Create and return header table row: 00985 return $this->addelement(1, $icon, $theData, ' class="c-headLine"', ''); 00986 } 00987 00988 /** 00989 * Creates a page browser for tables with many records 00990 * 00991 * @param string Distinguish between 'top' and 'bottom' part of the navigation (above or below the records) 00992 * @return string Navigation HTML 00993 * 00994 */ 00995 protected function renderListNavigation($renderPart = 'top') { 00996 $totalPages = ceil($this->totalItems / $this->iLimit); 00997 00998 $content = ''; 00999 $returnContent = ''; 01000 01001 // Show page selector if not all records fit into one page 01002 if ($totalPages > 1) { 01003 $first = $previous = $next = $last = $reload = ''; 01004 $listURL = $this->listURL('', $this->table); 01005 01006 // 1 = first page 01007 $currentPage = floor(($this->firstElementNumber + 1) / $this->iLimit) + 1; 01008 01009 // Compile first, previous, next, last and refresh buttons 01010 if ($currentPage > 1) { 01011 $labelFirst = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:first'); 01012 01013 $first = '<a href="' . $listURL . '&pointer=0">' . 01014 t3lib_iconWorks::getSpriteIcon('actions-view-paging-first', array('title'=> $labelFirst)) . 01015 '</a>'; 01016 } else { 01017 $first = t3lib_iconWorks::getSpriteIcon('actions-view-paging-first-disabled'); 01018 } 01019 01020 if (($currentPage - 1) > 0) { 01021 $labelPrevious = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:previous'); 01022 01023 $previous = '<a href="' . $listURL . '&pointer=' . (($currentPage - 2) * $this->iLimit) . '">' . 01024 t3lib_iconWorks::getSpriteIcon('actions-view-paging-previous', array('title' => $labelPrevious)) . 01025 '</a>'; 01026 } else { 01027 $previous = t3lib_iconWorks::getSpriteIcon('actions-view-paging-previous-disabled'); 01028 } 01029 01030 if (($currentPage + 1) <= $totalPages) { 01031 $labelNext = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:next'); 01032 01033 $next = '<a href="' . $listURL . '&pointer=' . (($currentPage) * $this->iLimit) . '">' . 01034 t3lib_iconWorks::getSpriteIcon('actions-view-paging-next', array('title' => $labelNext)) . 01035 '</a>'; 01036 } else { 01037 $next = t3lib_iconWorks::getSpriteIcon('actions-view-paging-next-disabled'); 01038 } 01039 01040 if ($currentPage != $totalPages) { 01041 $labelLast = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:last'); 01042 01043 $last = '<a href="' . $listURL . '&pointer=' . (($totalPages - 1) * $this->iLimit) . '">' . 01044 t3lib_iconWorks::getSpriteIcon('actions-view-paging-last', array('title' => $labelLast)) . 01045 '</a>'; 01046 } else { 01047 $last = t3lib_iconWorks::getSpriteIcon('actions-view-paging-last-disabled'); 01048 } 01049 01050 $reload = '<a href="#" onclick="document.dblistForm.action=\'' 01051 . $listURL . '&pointer=\'+calculatePointer(document.getElementById(\'jumpPage-' . $renderPart .'\').value); document.dblistForm.submit(); return true;" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:reload', TRUE) . '">' . 01052 t3lib_iconWorks::getSpriteIcon('actions-system-refresh') . 01053 '</a>'; 01054 01055 if ($renderPart === 'top') { 01056 // Add js to traverse a page select input to a pointer value 01057 $content = ' 01058 <script type="text/JavaScript"> 01059 /*<![CDATA[*/ 01060 01061 function calculatePointer(page) { 01062 if (page > ' . $totalPages . ') { 01063 page = ' . $totalPages . '; 01064 } 01065 01066 if (page < 1) { 01067 page = 1; 01068 } 01069 01070 pointer = (page - 1) * ' . $this->iLimit . '; 01071 01072 return pointer; 01073 } 01074 01075 /*]]>*/ 01076 </script> 01077 '; 01078 } 01079 $pageNumberInput = '<span> 01080 <input type="text" value="' . $currentPage 01081 . '" size="3" id="jumpPage-' . $renderPart . '" name="jumpPage-' . $renderPart . '" onkeyup="if (event.keyCode == Event.KEY_RETURN) { document.dblistForm.action=\'' . $listURL . '&pointer=\'+calculatePointer(this.value); document.dblistForm.submit(); } return true;" /> 01082 </span>'; 01083 $pageIndicator = '<span class="pageIndicator">' 01084 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:pageIndicator'), $pageNumberInput, $totalPages) 01085 . '</span>'; 01086 01087 if ($this->totalItems > ($this->firstElementNumber + $this->iLimit)) { 01088 $lastElementNumber = $this->firstElementNumber + $this->iLimit; 01089 } else { 01090 $lastElementNumber = $this->totalItems; 01091 } 01092 $rangeIndicator = '<span class="pageIndicator">' 01093 . sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:rangeIndicator'), $this->firstElementNumber + 1, $lastElementNumber) 01094 . '</span>'; 01095 01096 $content .= '<div id="typo3-dblist-pagination">' 01097 . $first . $previous 01098 . '<span class="bar"> </span>' 01099 . $rangeIndicator . '<span class="bar"> </span>' 01100 . $pageIndicator . '<span class="bar"> </span>' 01101 . $next . $last . '<span class="bar"> </span>' 01102 . $reload 01103 . '</div>'; 01104 01105 $data = Array(); 01106 $titleColumn = $this->fieldArray[0]; 01107 $data[$titleColumn] = $content; 01108 01109 $returnContent = $this->addElement(1, '', $data); 01110 } // end of if pages > 1 01111 01112 return $returnContent; 01113 } 01114 01115 01116 01117 01118 01119 01120 /********************************* 01121 * 01122 * Rendering of various elements 01123 * 01124 *********************************/ 01125 01126 /** 01127 * Creates the control panel for a single record in the listing. 01128 * 01129 * @param string The table 01130 * @param array The record for which to make the control panel. 01131 * @return string HTML table with the control panel (unless disabled) 01132 */ 01133 function makeControl($table,$row) { 01134 global $TCA, $LANG, $SOBE, $TYPO3_CONF_VARS; 01135 01136 if ($this->dontShowClipControlPanels) return ''; 01137 01138 // Initialize: 01139 t3lib_div::loadTCA($table); 01140 $cells=array(); 01141 01142 // If the listed table is 'pages' we have to request the permission settings for each page: 01143 if ($table=='pages') { 01144 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$row['uid'])); 01145 } 01146 01147 // This expresses the edit permissions for this particular element: 01148 $permsEdit = ($table=='pages' && ($localCalcPerms&2)) || ($table!='pages' && ($this->calcPerms&16)); 01149 01150 // "Show" link (only pages and tt_content elements) 01151 if ($table=='pages' || $table=='tt_content') { 01152 $params='&edit['.$table.']['.$row['uid'].']=edit'; 01153 $cells['view']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::viewOnClick($table=='tt_content'?$this->id.'#'.$row['uid']:$row['uid'], $this->backPath)).'" title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', TRUE).'">'. 01154 t3lib_iconWorks::getSpriteIcon('actions-document-view') . 01155 '</a>'; 01156 } elseif(!$this->table) { 01157 $cells['view'] = $this->spaceIcon; 01158 } 01159 01160 // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id) 01161 if ($permsEdit) { 01162 $params='&edit['.$table.']['.$row['uid'].']=edit'; 01163 $cells['edit']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'" title="'.$LANG->getLL('edit', TRUE).'">'. 01164 ( $TCA[$table]['ctrl']['readOnly'] ? t3lib_iconWorks::getSpriteIcon('actions-document-open-read-only') : t3lib_iconWorks::getSpriteIcon('actions-document-open') ). 01165 '</a>'; 01166 } elseif(!$this->table) { 01167 $cells['edit'] = $this->spaceIcon; 01168 } 01169 01170 // "Move" wizard link for pages/tt_content elements: 01171 if (($table=="tt_content" && $permsEdit) || ($table=='pages')) { 01172 $cells['move']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'move_el.php?table='.$table.'&uid='.$row['uid'].'\');').'" title="'.$LANG->getLL('move_' . ($table == 'tt_content' ? 'record' : 'page'), TRUE) . '">' . 01173 ($table == 'tt_content' ? t3lib_iconWorks::getSpriteIcon('actions-document-move') : t3lib_iconWorks::getSpriteIcon('actions-page-move')) . 01174 '</a>'; 01175 } elseif(!$this->table) { 01176 $cells['move'] = $this->spaceIcon; 01177 } 01178 01179 // If the extended control panel is enabled OR if we are seeing a single table: 01180 if ($SOBE->MOD_SETTINGS['bigControlPanel'] || $this->table) { 01181 01182 // "Info": (All records) 01183 $cells['viewBig']='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$table.'\', \''.$row['uid'].'\'); return false;').'" title="'.$LANG->getLL('showInfo', TRUE).'">'. 01184 t3lib_iconWorks::getSpriteIcon('actions-document-info') . 01185 '</a>'; 01186 01187 // If the table is NOT a read-only table, then show these links: 01188 if (!$TCA[$table]['ctrl']['readOnly']) { 01189 01190 // "Revert" link (history/undo) 01191 $cells['history']='<a href="#" onclick="'.htmlspecialchars('return jumpExt(\''.$this->backPath.'show_rechis.php?element='.rawurlencode($table.':'.$row['uid']).'\',\'#latest\');').'" title="'.$LANG->getLL('history', TRUE).'">'. 01192 t3lib_iconWorks::getSpriteIcon('actions-document-history-open') . 01193 '</a>'; 01194 01195 // Versioning: 01196 if (t3lib_extMgm::isLoaded('version')) { 01197 $vers = t3lib_BEfunc::selectVersionsOfRecord($table, $row['uid'], 'uid', $GLOBALS['BE_USER']->workspace, FALSE, $row); 01198 if (is_array($vers)) { // If table can be versionized. 01199 $versionIcon = 'no-version'; 01200 if (count($vers) > 1) { 01201 $versionIcon = count($vers) - 1; 01202 } 01203 01204 $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', TRUE) . '">' . 01205 t3lib_iconWorks::getSpriteIcon('status-version-' . $versionIcon) . 01206 '</a>'; 01207 } elseif(!$this->table) { 01208 $cells['version'] = $this->spaceIcon; 01209 } 01210 } 01211 01212 // "Edit Perms" link: 01213 if ($table == 'pages' && $GLOBALS['BE_USER']->check('modules','web_perm') && t3lib_extMgm::isLoaded('perm')) { 01214 $cells['perms'] = 01215 '<a href="' . 01216 htmlspecialchars( 01217 t3lib_extMgm::extRelPath('perm') . 'mod1/index.php' . 01218 '?id=' . $row['uid'] . '&return_id=' . $row['uid'] . '&edit=1' 01219 ) . 01220 '" title="' . $LANG->getLL('permissions', TRUE) . 01221 '">'. 01222 t3lib_iconWorks::getSpriteIcon('status-status-locked') . 01223 '</a>'; 01224 } elseif(!$this->table && $GLOBALS['BE_USER']->check('modules','web_perm')) { 01225 $cells['perms'] = $this->spaceIcon; 01226 } 01227 01228 // "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): 01229 if ($TCA[$table]['ctrl']['sortby'] || $TCA[$table]['ctrl']['useColumnsForDefaultValues']) { 01230 if ( 01231 ($table!='pages' && ($this->calcPerms&16)) || // For NON-pages, must have permission to edit content on this parent page 01232 ($table=='pages' && ($this->calcPerms&8)) // For pages, must have permission to create new pages here. 01233 ) { 01234 if ($this->showNewRecLink($table)) { 01235 $params='&edit['.$table.']['.(-($row['_MOVE_PLH']?$row['_MOVE_PLH_uid']:$row['uid'])).']=new'; 01236 $cells['new']='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'" title="'.$LANG->getLL('new'.($table=='pages'?'Page':'Record'), TRUE).'">'. 01237 ($table=='pages' ? t3lib_iconWorks::getSpriteIcon('actions-page-new') : t3lib_iconWorks::getSpriteIcon('actions-document-new')) . 01238 '</a>'; 01239 } 01240 } 01241 } elseif(!$this->table) { 01242 $cells['new'] = $this->spaceIcon; 01243 } 01244 01245 // "Up/Down" links 01246 if ($permsEdit && $TCA[$table]['ctrl']['sortby'] && !$this->sortField && !$this->searchLevels) { 01247 if (isset($this->currentTable['prev'][$row['uid']])) { // Up 01248 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prev'][$row['uid']]; 01249 $cells['moveUp']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'" title="'.$LANG->getLL('moveUp', TRUE) . '">' . 01250 t3lib_iconWorks::getSpriteIcon('actions-move-up') . 01251 '</a>'; 01252 } else { 01253 $cells['moveUp'] = $this->spaceIcon; 01254 } 01255 if ($this->currentTable['next'][$row['uid']]) { // Down 01256 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['next'][$row['uid']]; 01257 $cells['moveDown']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'" title="'.$LANG->getLL('moveDown', TRUE) . '">' . 01258 t3lib_iconWorks::getSpriteIcon('actions-move-down') . 01259 '</a>'; 01260 } else { 01261 $cells['moveDown'] = $this->spaceIcon; 01262 } 01263 } elseif(!$this->table) { 01264 $cells['moveUp'] = $this->spaceIcon; 01265 $cells['moveDown'] = $this->spaceIcon; 01266 } 01267 01268 // "Hide/Unhide" links: 01269 $hiddenField = $TCA[$table]['ctrl']['enablecolumns']['disabled']; 01270 if ($permsEdit && $hiddenField && $TCA[$table]['columns'][$hiddenField] && (!$TCA[$table]['columns'][$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$table.':'.$hiddenField))) { 01271 if ($row[$hiddenField]) { 01272 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=0'; 01273 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'" title="'.$LANG->getLL('unHide' . ($table == 'pages' ? 'Page' : ''), TRUE) . '">' . 01274 t3lib_iconWorks::getSpriteIcon('actions-edit-unhide') . 01275 '</a>'; 01276 } else { 01277 $params='&data['.$table.']['.$row['uid'].']['.$hiddenField.']=1'; 01278 $cells['hide']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'" title="'.$LANG->getLL('hide' . ($table == 'pages' ? 'Page' : ''), TRUE) . '">' . 01279 t3lib_iconWorks::getSpriteIcon('actions-edit-hide') . 01280 '</a>'; 01281 } 01282 } elseif(!$this->table) { 01283 $cells['hide'] = $this->spaceIcon; 01284 } 01285 01286 // "Delete" link: 01287 if (($table=='pages' && ($localCalcPerms&4)) || ($table!='pages' && ($this->calcPerms&16))) { 01288 $titleOrig = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE); 01289 $title = t3lib_div::slashJS(t3lib_div::fixed_lgd_cs($titleOrig, $this->fixedL), 1); 01290 $params = '&cmd['.$table.']['.$row['uid'].'][delete]=1'; 01291 01292 $refCountMsg = t3lib_BEfunc::referenceCount( 01293 $table, 01294 $row['uid'], 01295 ' ' . $GLOBALS['LANG']->sL( 01296 'LLL:EXT:lang/locallang_core.xml:labels.referencesToRecord' 01297 ), 01298 $this->getReferenceCount($table, $row['uid']) 01299 ) . 01300 t3lib_BEfunc::translationCount($table, $row['uid'], ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.translationsOfRecord')); 01301 $cells['delete']='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$LANG->JScharCode($LANG->getLL('deleteWarning').' "'. $title.'" '.$refCountMsg).')) {jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');} return false;').'" title="' . $LANG->getLL('delete', TRUE) . '">' . 01302 t3lib_iconWorks::getSpriteIcon('actions-edit-delete') . 01303 '</a>'; 01304 } elseif(!$this->table) { 01305 $cells['delete'] = $this->spaceIcon; 01306 } 01307 01308 // "Levels" links: Moving pages into new levels... 01309 if ($permsEdit && $table=='pages' && !$this->searchLevels) { 01310 01311 // Up (Paste as the page right after the current parent page) 01312 if ($this->calcPerms&8) { 01313 $params='&cmd['.$table.']['.$row['uid'].'][move]='.-$this->id; 01314 $cells['moveLeft']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'" title="'.$LANG->getLL('prevLevel', TRUE).'">'. 01315 t3lib_iconWorks::getSpriteIcon('actions-move-left') . 01316 '</a>'; 01317 } 01318 // Down (Paste as subpage to the page right above) 01319 if ($this->currentTable['prevUid'][$row['uid']]) { 01320 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$this->currentTable['prevUid'][$row['uid']])); 01321 if ($localCalcPerms&8) { 01322 $params='&cmd['.$table.']['.$row['uid'].'][move]='.$this->currentTable['prevUid'][$row['uid']]; 01323 $cells['moveRight']='<a href="#" onclick="'.htmlspecialchars('return jumpToUrl(\''.$SOBE->doc->issueCommand($params,-1).'\');').'" title="'.$LANG->getLL('nextLevel', TRUE).'">'. 01324 t3lib_iconWorks::getSpriteIcon('actions-move-right') . 01325 '</a>'; 01326 } else { 01327 $cells['moveRight'] = $this->spaceIcon; 01328 } 01329 } else { 01330 $cells['moveRight'] = $this->spaceIcon; 01331 } 01332 } elseif(!$this->table) { 01333 $cells['moveLeft'] = $this->spaceIcon; 01334 $cells['moveRight'] = $this->spaceIcon; 01335 } 01336 } 01337 } 01338 01339 01340 /** 01341 * @hook recStatInfoHooks: Allows to insert HTML before record icons on various places 01342 * @date 2007-09-22 01343 * @request Kasper Skårhøj <kasper2007@typo3.com> 01344 */ 01345 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) { 01346 $stat=''; 01347 $_params = array($table,$row['uid']); 01348 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) { 01349 $stat.=t3lib_div::callUserFunction($_funcRef,$_params,$this); 01350 } 01351 $cells['stat'] = $stat; 01352 } 01353 /** 01354 * @hook makeControl: Allows to change control icons of records in list-module 01355 * @date 2007-11-20 01356 * @request Bernhard Kraft <krafbt@kraftb.at> 01357 * @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. 01358 */ 01359 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) { 01360 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) { 01361 $hookObject = t3lib_div::getUserObj($classData); 01362 if(!($hookObject instanceof localRecordList_actionsHook)) { 01363 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567840); 01364 } 01365 $cells = $hookObject->makeControl($table, $row, $cells, $this); 01366 } 01367 } 01368 01369 // Compile items into a DIV-element: 01370 return ' 01371 <!-- CONTROL PANEL: '.$table.':'.$row['uid'].' --> 01372 <div class="typo3-DBctrl">'.implode('',$cells).'</div>'; 01373 } 01374 01375 /** 01376 * Creates the clipboard panel for a single record in the listing. 01377 * 01378 * @param string The table 01379 * @param array The record for which to make the clipboard panel. 01380 * @return string HTML table with the clipboard panel (unless disabled) 01381 */ 01382 function makeClip($table,$row) { 01383 global $TCA, $LANG, $TYPO3_CONF_VARS; 01384 01385 // Return blank, if disabled: 01386 if ($this->dontShowClipControlPanels) return ''; 01387 $cells=array(); 01388 01389 $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon; 01390 //enables to hide the copy, cut and paste icons for localized records - doesn't make much sense to perform these options for them 01391 $isL10nOverlay = $this->localizationView && $table != 'pages_language_overlay' && $row[$TCA[$table]['ctrl']['transOrigPointerField']] != 0; 01392 // Return blank, if disabled: 01393 // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel: 01394 if ($this->clipObj->current=='normal') { // For the "Normal" pad: 01395 01396 // Show copy/cut icons: 01397 $isSel = (string)$this->clipObj->isSelected($table,$row['uid']); 01398 $cells['copy'] = $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'" title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.copy', TRUE).'">'. 01399 ((!$isSel=='copy') ? t3lib_iconWorks::getSpriteIcon('actions-edit-copy') : t3lib_iconWorks::getSpriteIcon('actions-edit-copy-release')) . 01400 '</a>'; 01401 $cells['cut'] = $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'" title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.cut', TRUE).'">'. 01402 ((!$isSel=='cut') ? t3lib_iconWorks::getSpriteIcon('actions-edit-cut') : t3lib_iconWorks::getSpriteIcon('actions-edit-cut-release')) . 01403 '</a>'; 01404 01405 } else { // For the numeric clipboard pads (showing checkboxes where one can select elements on/off) 01406 01407 // Setting name of the element in ->CBnames array: 01408 $n=$table.'|'.$row['uid']; 01409 $this->CBnames[]=$n; 01410 01411 // Check if the current element is selected and if so, prepare to set the checkbox as selected: 01412 $checked = ($this->clipObj->isSelected($table,$row['uid'])?' checked="checked"':''); 01413 01414 // If the "duplicateField" value is set then select all elements which are duplicates... 01415 if ($this->duplicateField && isset($row[$this->duplicateField])) { 01416 $checked=''; 01417 if (in_array($row[$this->duplicateField], $this->duplicateStack)) { 01418 $checked=' checked="checked"'; 01419 } 01420 $this->duplicateStack[] = $row[$this->duplicateField]; 01421 } 01422 01423 // Adding the checkbox to the panel: 01424 $cells['select'] = $isL10nOverlay ? $this->spaceIcon : '<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />'; 01425 } 01426 01427 // Now, looking for selected elements from the current table: 01428 $elFromTable = $this->clipObj->elFromTable($table); 01429 if (count($elFromTable) && $TCA[$table]['ctrl']['sortby']) { // IF elements are found and they can be individually ordered, then add a "paste after" icon: 01430 $cells['pasteAfter'] = $isL10nOverlay ? $this->spaceIcon : '<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,-$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'after',$elFromTable)).'" title="'.$LANG->getLL('clip_pasteAfter', TRUE).'">'. 01431 t3lib_iconWorks::getSpriteIcon('actions-document-paste-after') . 01432 '</a>'; 01433 } 01434 01435 // Now, looking for elements in general: 01436 $elFromTable = $this->clipObj->elFromTable(''); 01437 if ($table=='pages' && count($elFromTable)) { 01438 $cells['pasteInto']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl('',$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'into',$elFromTable)).'" title="'.$LANG->getLL('clip_pasteInto', TRUE).'">'. 01439 t3lib_iconWorks::getSpriteIcon('actions-document-paste-into') . 01440 '</a>'; 01441 } 01442 01443 /* 01444 * @hook makeClip: Allows to change clip-icons of records in list-module 01445 * @date 2007-11-20 01446 * @request Bernhard Kraft <krafbt@kraftb.at> 01447 * @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. 01448 */ 01449 if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) { 01450 foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) { 01451 $hookObject = t3lib_div::getUserObj($classData); 01452 if(!($hookObject instanceof localRecordList_actionsHook)) { 01453 throw new UnexpectedValueException('$hookObject must implement interface localRecordList_actionsHook', 1195567845); 01454 } 01455 $cells = $hookObject->makeClip($table, $row, $cells, $this); 01456 } 01457 } 01458 01459 // Compile items into a DIV-element: 01460 return ' <!-- CLIPBOARD PANEL: '.$table.':'.$row['uid'].' --> 01461 <div class="typo3-clipCtrl">'.implode('',$cells).'</div>'; 01462 } 01463 01464 /** 01465 * Make reference count 01466 * 01467 * @param string Table name 01468 * @param integer UID of record 01469 * @return string HTML-table 01470 * 01471 * @deprecated since 4.4, will be removed in TYPO3 4.6 - Use createReferenceHtml() instead 01472 */ 01473 function makeRef($table,$uid) { 01474 t3lib_div::logDeprecatedFunction(); 01475 01476 // Compile information for title tag: 01477 $infoData=array(); 01478 if (is_array($this->references)) { 01479 foreach ($this->references as $row) { 01480 $infoData[]=$row['tablename'].':'.$row['recuid'].':'.$row['field']; 01481 } 01482 } 01483 01484 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>' : ''; 01485 } 01486 01487 /** 01488 * Creates the HTML for a reference count for the record with the UID $uid 01489 * in the table $tableName. 01490 * 01491 * @param string $tableName 01492 * table name of the referenced record, must not be empty 01493 * @param integer $uid 01494 * UID of the referenced record, must be > 0 01495 * 01496 * @return string HTML of reference a link, will be empty if there are no 01497 * references to the corresponding record 01498 */ 01499 protected function createReferenceHtml($tableName, $uid) { 01500 $referenceCount = $this->getReferenceCount($tableName, $uid); 01501 if ($referenceCount == 0) { 01502 return ''; 01503 } 01504 01505 $queryResult = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 01506 'tablename, recuid, field', 01507 'sys_refindex', 01508 'ref_table = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr( 01509 $tableName, 'sys_refindex' 01510 ) . 01511 ' AND ref_uid = ' . $uid . 01512 ' AND deleted = 0', 01513 '', 01514 '', 01515 '0,20' 01516 ); 01517 01518 $referenceTitles = array(); 01519 01520 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($queryResult)) { 01521 $referenceTitles[] = $row['tablename'] . ':' . $row['recuid'] . 01522 ':' . $row['field']; 01523 if (strlen(implode(' / ', $referenceTitles)) >= 100) { 01524 break; 01525 } 01526 } 01527 $GLOBALS['TYPO3_DB']->sql_free_result($queryResult); 01528 01529 return '<a href="#" ' . 01530 'onclick="' . htmlspecialchars( 01531 'top.launchView(\'' . $tableName . '\', \'' . $uid . 01532 '\'); return false;' 01533 ) . '" ' . 01534 'title="' . htmlspecialchars( 01535 t3lib_div::fixed_lgd_cs(implode(' / ', $referenceTitles), 100) 01536 ) . '">' . $referenceCount . '</a>'; 01537 } 01538 01539 /** 01540 * Creates the localization panel 01541 * 01542 * @param string The table 01543 * @param array The record for which to make the localization panel. 01544 * @return array Array with key 0/1 with content for column 1 and 2 01545 */ 01546 function makeLocalizationPanel($table,$row) { 01547 global $TCA,$LANG; 01548 01549 $out = array( 01550 0 => '', 01551 1 => '', 01552 ); 01553 01554 $translations = $this->translateTools->translationInfo($table, $row['uid'], 0, $row, $this->selFieldList); 01555 $this->translations = $translations['translations']; 01556 01557 // Language title and icon: 01558 $out[0] = $this->languageFlag($row[$TCA[$table]['ctrl']['languageField']]); 01559 01560 if (is_array($translations)) { 01561 01562 // Traverse page translations and add icon for each language that does NOT yet exist: 01563 $lNew = ''; 01564 foreach($this->pageOverlays as $lUid_OnPage => $lsysRec) { 01565 if (!isset($translations['translations'][$lUid_OnPage]) && $GLOBALS['BE_USER']->checkLanguageAccess($lUid_OnPage)) { 01566 $url = substr($this->listURL(), strlen($this->backPath)); 01567 $href = $GLOBALS['SOBE']->doc->issueCommand( 01568 '&cmd[' . $table . '][' . $row['uid'] . '][localize]=' . $lUid_OnPage, 01569 $url . '&justLocalized=' . rawurlencode($table . ':' . $row['uid'] . ':' . $lUid_OnPage) 01570 ); 01571 $language = t3lib_BEfunc::getRecord('sys_language', $lUid_OnPage, 'title'); 01572 if ($this->languageIconTitles[$lUid_OnPage]['flagIcon']) { 01573 $lC = t3lib_iconWorks::getSpriteIcon($this->languageIconTitles[$lUid_OnPage]['flagIcon']);; 01574 } else { 01575 $lC = $this->languageIconTitles[$lUid_OnPage]['title']; 01576 } 01577 $lC = '<a href="' . htmlspecialchars($href) . '" title="' . htmlspecialchars($language['title']) . '">' . $lC . '</a> '; 01578 01579 $lNew.=$lC; 01580 } 01581 } 01582 01583 if ($lNew) $out[1].= $lNew; 01584 } else if ($row['l18n_parent']) { 01585 $out[0] = ' '.$out[0]; 01586 } 01587 01588 01589 return $out; 01590 } 01591 01592 /** 01593 * Create the selector box for selecting fields to display from a table: 01594 * 01595 * @param string Table name 01596 * @param boolean If true, form-fields will be wrapped around the table. 01597 * @return string HTML table with the selector box (name: displayFields['.$table.'][]) 01598 */ 01599 function fieldSelectBox($table,$formFields=1) { 01600 global $TCA, $LANG; 01601 01602 // Init: 01603 t3lib_div::loadTCA($table); 01604 $formElements=array('',''); 01605 if ($formFields) { 01606 $formElements=array('<form action="'.htmlspecialchars($this->listURL()).'" method="post">','</form>'); 01607 } 01608 01609 // Load already selected fields, if any: 01610 $setFields=is_array($this->setFields[$table]) ? $this->setFields[$table] : array(); 01611 01612 // Request fields from table: 01613 $fields = $this->makeFieldList($table, false, true); 01614 01615 // Add pseudo "control" fields 01616 $fields[]='_PATH_'; 01617 $fields[]='_REF_'; 01618 $fields[]='_LOCALIZATION_'; 01619 $fields[]='_CONTROL_'; 01620 $fields[]='_CLIPBOARD_'; 01621 01622 // Create an option for each field: 01623 $opt=array(); 01624 $opt[] = '<option value=""></option>'; 01625 foreach($fields as $fN) { 01626 $fL = is_array($TCA[$table]['columns'][$fN]) ? rtrim($LANG->sL($TCA[$table]['columns'][$fN]['label']),':') : '['.$fN.']'; // Field label 01627 $opt[] = ' 01628 <option value="'.$fN.'"'.(in_array($fN,$setFields)?' selected="selected"':'').'>'.htmlspecialchars($fL).'</option>'; 01629 } 01630 01631 // Compile the options into a multiple selector box: 01632 $lMenu = ' 01633 <select size="'.t3lib_div::intInRange(count($fields)+1,3,20).'" multiple="multiple" name="displayFields['.$table.'][]">'.implode('',$opt).' 01634 </select> 01635 '; 01636 01637 // Table with the field selector:: 01638 $content.= ' 01639 '.$formElements[0].' 01640 01641 <!-- 01642 Field selector for extended table view: 01643 --> 01644 <table border="0" cellpadding="0" cellspacing="0" id="typo3-dblist-fieldSelect"> 01645 <tr> 01646 <td>'.$lMenu.'</td> 01647 <td><input type="submit" name="search" value="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.setFields',1).'" /></td> 01648 </tr> 01649 </table> 01650 '.$formElements[1]; 01651 return $content; 01652 } 01653 01654 01655 01656 01657 01658 01659 01660 01661 01662 01663 01664 /********************************* 01665 * 01666 * Helper functions 01667 * 01668 *********************************/ 01669 01670 /** 01671 * Creates a link around $string. The link contains an onclick action which submits the script with some clipboard action. 01672 * Currently, this is used for setting elements / delete elements. 01673 * 01674 * @param string The HTML content to link (image/text) 01675 * @param string Table name 01676 * @param string Clipboard command (eg. "setCB" or "delete") 01677 * @param string Warning text, if any ("delete" uses this for confirmation) 01678 * @return string <a> tag wrapped link. 01679 */ 01680 function linkClipboardHeaderIcon($string,$table,$cmd,$warning='') { 01681 $onClickEvent = 'document.dblistForm.cmd.value=\''.$cmd.'\';document.dblistForm.cmd_table.value=\''.$table.'\';document.dblistForm.submit();'; 01682 if ($warning) $onClickEvent = 'if (confirm('.$GLOBALS['LANG']->JScharCode($warning).')){'.$onClickEvent.'}'; 01683 return '<a href="#" onclick="'.htmlspecialchars($onClickEvent.'return false;').'">'.$string.'</a>'; 01684 } 01685 01686 /** 01687 * Returns true if a numeric clipboard pad is selected/active 01688 * 01689 * @return boolean 01690 */ 01691 function clipNumPane() { 01692 return in_Array('_CLIPBOARD_',$this->fieldArray) && $this->clipObj->current!='normal'; 01693 } 01694 01695 /** 01696 * Creates a sort-by link on the input string ($code). 01697 * It will automatically detect if sorting should be ascending or descending depending on $this->sortRev. 01698 * Also some fields will not be possible to sort (including if single-table-view is disabled). 01699 * 01700 * @param string The string to link (text) 01701 * @param string The fieldname represented by the title ($code) 01702 * @param string Table name 01703 * @return string Linked $code variable 01704 */ 01705 function addSortLink($code,$field,$table) { 01706 01707 // Certain circumstances just return string right away (no links): 01708 if ($field=='_CONTROL_' || $field=='_LOCALIZATION_' || $field=='_CLIPBOARD_' || $field=='_REF_' || $this->disableSingleTableView) return $code; 01709 01710 // If "_PATH_" (showing record path) is selected, force sorting by pid field (will at least group the records!) 01711 if ($field=='_PATH_') $field=pid; 01712 01713 // Create the sort link: 01714 $sortUrl = $this->listURL('',-1,'sortField,sortRev,table').'&table='.$table.'&sortField='.$field.'&sortRev='.($this->sortRev || ($this->sortField!=$field)?0:1); 01715 $sortArrow = ($this->sortField==$field?'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/red'.($this->sortRev?'up':'down').'.gif','width="7" height="4"').' alt="" />':''); 01716 01717 // Return linked field: 01718 return '<a href="'.htmlspecialchars($sortUrl).'">'.$code. 01719 $sortArrow. 01720 '</a>'; 01721 } 01722 01723 /** 01724 * Returns the path for a certain pid 01725 * The result is cached internally for the session, thus you can call this function as much as you like without performance problems. 01726 * 01727 * @param integer The page id for which to get the path 01728 * @return string The path. 01729 */ 01730 function recPath($pid) { 01731 if (!isset($this->recPath_cache[$pid])) { 01732 $this->recPath_cache[$pid] = t3lib_BEfunc::getRecordPath($pid,$this->perms_clause,20); 01733 } 01734 return $this->recPath_cache[$pid]; 01735 } 01736 01737 /** 01738 * Returns true if a link for creating new records should be displayed for $table 01739 * 01740 * @param string Table name 01741 * @return boolean Returns true if a link for creating new records should be displayed for $table 01742 * @see SC_db_new::showNewRecLink 01743 */ 01744 function showNewRecLink($table) { 01745 // No deny/allow tables are set: 01746 if (!count($this->allowedNewTables) && !count($this->deniedNewTables)) { 01747 return true; 01748 // If table is not denied (which takes precedence over allowed tables): 01749 } elseif (!in_array($table, $this->deniedNewTables) && (!count($this->allowedNewTables) || in_array($table, $this->allowedNewTables))) { 01750 return true; 01751 // If table is denied or allowed tables are set, but table is not part of: 01752 } else { 01753 return false; 01754 } 01755 } 01756 01757 /** 01758 * 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. 01759 * Uses REQUEST_URI as value. 01760 * 01761 * @return string 01762 */ 01763 function makeReturnUrl() { 01764 return '&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')); 01765 } 01766 01767 01768 01769 01770 01771 01772 01773 01774 01775 01776 01777 /************************************ 01778 * 01779 * CSV related functions 01780 * 01781 ************************************/ 01782 01783 /** 01784 * Initializes internal csvLines array with the header of field names 01785 * 01786 * @return void 01787 */ 01788 protected function initCSV() { 01789 $this->addHeaderRowToCSV(); 01790 } 01791 01792 /** 01793 * Add header line with field names as CSV line 01794 * 01795 * @return void 01796 */ 01797 protected function addHeaderRowToCSV() { 01798 // Add header row, control fields will be reduced inside addToCSV() 01799 $this->addToCSV(array_combine($this->fieldArray, $this->fieldArray)); 01800 } 01801 01802 /** 01803 * Adds selected columns of one table row as CSV line. 01804 * 01805 * @param array Record array, from which the values of fields found in $this->fieldArray will be listed in the CSV output. 01806 * @param string Table name @deprecated since 4.4 01807 * @return void 01808 */ 01809 protected function addToCSV(array $row = array(), $table = '') { 01810 $rowReducedByControlFields = self::removeControlFieldsFromFieldRow($row); 01811 $rowReducedToSelectedColumns = array_intersect_key($rowReducedByControlFields, array_flip($this->fieldArray)); 01812 $this->setCsvRow($rowReducedToSelectedColumns); 01813 } 01814 01815 /** 01816 * Remove control fields from row for CSV export 01817 * 01818 * @param array fieldNames => fieldValues 01819 * @return array Input array reduces by control fields 01820 */ 01821 protected static function removeControlFieldsFromFieldRow(array $row = array()) { 01822 // Possible control fields in a list row 01823 $controlFields = array( 01824 '_PATH_', 01825 '_REF_', 01826 '_CONTROL_', 01827 '_AFTERCONTROL_', 01828 '_AFTERREF_', 01829 '_CLIPBOARD_', 01830 '_LOCALIZATION_', 01831 '_LOCALIZATION_b', 01832 ); 01833 return array_diff_key($row, array_flip($controlFields)); 01834 } 01835 01836 01837 /** 01838 * Adds input row of values to the internal csvLines array as a CSV formatted line 01839 * 01840 * @param array Array with values to be listed. 01841 * @return void 01842 */ 01843 function setCsvRow($csvRow) { 01844 $this->csvLines[] = t3lib_div::csvValues($csvRow); 01845 } 01846 01847 /** 01848 * Compiles the internal csvLines array to a csv-string and outputs it to the browser. 01849 * This function exits! 01850 * 01851 * @param string Filename prefix: 01852 * @return void EXITS php execusion! 01853 */ 01854 function outputCSV($prefix) { 01855 01856 // Setting filename: 01857 $filename=$prefix.'_'.date('dmy-Hi').'.csv'; 01858 01859 // Creating output header: 01860 $mimeType = 'application/octet-stream'; 01861 Header('Content-Type: '.$mimeType); 01862 Header('Content-Disposition: attachment; filename='.$filename); 01863 01864 // Printing the content of the CSV lines: 01865 echo implode(chr(13).chr(10),$this->csvLines); 01866 01867 // Exits: 01868 exit; 01869 } 01870 } 01871 01872 01873 01874 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc'])) { 01875 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/class.db_list_extra.inc']); 01876 } 01877 01878 ?>
1.8.0