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