PageRenderTime 92ms CodeModel.GetById 41ms RepoModel.GetById 0ms app.codeStats 1ms

/typo3/class.db_list_extra.inc

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