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