[TASK] Fix CGL violations against InlineControlStructure
[Packages/TYPO3.CMS.git] / typo3 / class.db_list.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 /**
29 * Child class for rendering of Web > List (not the final class. see class.db_list_extra)
30 * Shared between Web>List (db_list.php) and Web>Page (sysext/cms/layout/db_layout.php)
31 *
32 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
33 * @package TYPO3
34 * @subpackage core
35 * @see localRecordList
36 */
37 class recordList extends t3lib_recordList {
38
39 // External, static:
40 // Specify a list of tables which are the only ones allowed to be displayed.
41 var $tableList = '';
42 // Return URL
43 var $returnUrl = '';
44 // Boolean. Thumbnails on records containing files (pictures)
45 var $thumbs = 0;
46 // default Max items shown per table in "multi-table mode", may be overridden by tables.php
47 var $itemsLimitPerTable = 20;
48 // default Max items shown per table in "single-table mode", may be overridden by tables.php
49 var $itemsLimitSingleTable = 100;
50 var $widthGif = '<img src="clear.gif" width="1" height="4" hspace="160" alt="" />';
51 // Current script name
52 var $script = 'index.php';
53 // Indicates if all available fields for a user should be selected or not.
54 var $allFields = 0;
55 // Whether to show localization view or not.
56 var $localizationView = FALSE;
57
58 // Internal, static: GPvar:
59 // If set, csvList is outputted.
60 var $csvOutput = FALSE;
61 // Field, to sort list by
62 var $sortField;
63 // Field, indicating to sort in reverse order.
64 var $sortRev;
65 // Array, containing which fields to display in extended mode
66 var $displayFields;
67 // String, can contain the field name from a table which must have duplicate values marked.
68 var $duplicateField;
69
70 // Internal, static:
71 // Page id
72 var $id;
73 // Tablename if single-table mode
74 var $table = '';
75 // If TRUE, records are listed only if a specific table is selected.
76 var $listOnlyInSingleTableMode = FALSE;
77 // Pointer for browsing list
78 var $firstElementNumber = 0;
79 // Search string
80 var $searchString = '';
81 // Levels to search down.
82 var $searchLevels = '';
83 // Number of records to show
84 var $showLimit = 0;
85 // List of ids from which to select/search etc. (when search-levels are set high). See start()
86 var $pidSelect = '';
87 // Page select permissions
88 var $perms_clause = '';
89 // Some permissions...
90 var $calcPerms = 0;
91 // Mode for what happens when a user clicks the title of a record.
92 var $clickTitleMode = '';
93 // Shared module configuration, used by localization features
94 var $modSharedTSconfig = array();
95 // Loaded with page record with version overlay if any.
96 var $pageRecord = array();
97 // Tables which should not get listed
98 var $hideTables = '';
99
100 /**
101 * Tables which should not list their translations
102 * @var $hideTranslations string
103 */
104 public $hideTranslations = '';
105 //TSconfig which overwrites TCA-Settings
106 var $tableTSconfigOverTCA = array();
107 // Array of collapsed / uncollapsed tables in multi table view
108 var $tablesCollapsed = array();
109
110 // Internal, dynamic:
111 // JavaScript code accumulation
112 var $JScode = '';
113 // HTML output
114 var $HTMLcode = '';
115 // "LIMIT " in SQL...
116 var $iLimit = 0;
117 // Counting the elements no matter what...
118 var $eCounter = 0;
119 // Set to the total number of items for a table when selecting.
120 var $totalItems = '';
121 // Cache for record path
122 var $recPath_cache = array();
123 // Fields to display for the current table
124 var $setFields = array();
125 // Used for tracking next/prev uids
126 var $currentTable = array();
127 // Used for tracking duplicate values of fields
128 var $duplicateStack = array();
129 // module configuratio
130 var $modTSconfig;
131
132 /**
133 * Initializes the list generation
134 *
135 * @param integer $id Page id for which the list is rendered. Must be >= 0
136 * @param string $table Tablename - if extended mode where only one table is listed at a time.
137 * @param integer $pointer Browsing pointer.
138 * @param string $search Search word, if any
139 * @param integer $levels Number of levels to search down the page tree
140 * @param integer $showLimit Limit of records to be listed.
141 * @return void
142 */
143 function start($id, $table, $pointer, $search = '', $levels = '', $showLimit = 0) {
144
145 // Setting internal variables:
146 // sets the parent id
147 $this->id = intval($id);
148 if ($GLOBALS['TCA'][$table]) {
149 // Setting single table mode, if table exists:
150 $this->table = $table;
151 }
152 $this->firstElementNumber = $pointer;
153 $this->searchString = trim($search);
154 $this->searchLevels = trim($levels);
155 $this->showLimit = t3lib_utility_Math::forceIntegerInRange($showLimit, 0, 10000);
156
157 // Setting GPvars:
158 $this->csvOutput = t3lib_div::_GP('csv') ? TRUE : FALSE;
159 $this->sortField = t3lib_div::_GP('sortField');
160 $this->sortRev = t3lib_div::_GP('sortRev');
161 $this->displayFields = t3lib_div::_GP('displayFields');
162 $this->duplicateField = t3lib_div::_GP('duplicateField');
163
164 if (t3lib_div::_GP('justLocalized')) {
165 $this->localizationRedirect(t3lib_div::_GP('justLocalized'));
166 }
167
168 // Init dynamic vars:
169 $this->counter = 0;
170 $this->JScode = '';
171 $this->HTMLcode = '';
172
173 // Limits
174 if (isset($this->modTSconfig['properties']['itemsLimitPerTable'])) {
175 $this->itemsLimitPerTable = t3lib_utility_Math::forceIntegerInRange(intval($this->modTSconfig['properties']['itemsLimitPerTable']), 1, 10000);
176 }
177 if (isset($this->modTSconfig['properties']['itemsLimitSingleTable'])) {
178 $this->itemsLimitSingleTable = t3lib_utility_Math::forceIntegerInRange(intval($this->modTSconfig['properties']['itemsLimitSingleTable']), 1, 10000);
179 }
180
181 // Set search levels:
182 $searchLevels = intval($this->searchLevels);
183 $this->perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
184
185 // This will hide records from display - it has nothing todo with user rights!!
186 if ($pidList = $GLOBALS['BE_USER']->getTSConfigVal('options.hideRecords.pages')) {
187 if ($pidList = $GLOBALS['TYPO3_DB']->cleanIntList($pidList)) {
188 $this->perms_clause .= ' AND pages.uid NOT IN ('.$pidList.')';
189 }
190 }
191
192 // Get configuration of collapsed tables from user uc and merge with sanitized GP vars
193 $this->tablesCollapsed = is_array($GLOBALS['BE_USER']->uc['moduleData']['list']) ? $GLOBALS['BE_USER']->uc['moduleData']['list'] : array();
194 $collapseOverride = t3lib_div::_GP('collapse');
195 if (is_array($collapseOverride)) {
196 foreach ($collapseOverride as $collapseTable => $collapseValue) {
197 if (is_array($GLOBALS['TCA'][$collapseTable]) && ($collapseValue == 0 || $collapseValue == 1)) {
198 $this->tablesCollapsed[$collapseTable] = $collapseValue;
199 }
200 }
201 // Save modified user uc
202 $GLOBALS['BE_USER']->uc['moduleData']['list'] = $this->tablesCollapsed;
203 $GLOBALS['BE_USER']->writeUC($GLOBALS['BE_USER']->uc);
204 if (t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl'))) {
205 $location = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl'));
206 t3lib_utility_Http::redirect($location);
207 }
208 }
209
210 if ($searchLevels > 0) {
211 $tree = $this->getTreeObject($this->id, $searchLevels, $this->perms_clause);
212 $pidList = implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($tree->ids));
213 $this->pidSelect = 'pid IN (' . $pidList . ')';
214 } elseif ($searchLevels < 0) {
215 // Search everywhere
216 $this->pidSelect = '1=1';
217 } else {
218 $this->pidSelect = 'pid=' . intval($id);
219 }
220
221 // Initialize languages:
222 if ($this->localizationView) {
223 $this->initializeLanguages();
224 }
225 }
226
227 /**
228 * Traverses the table(s) to be listed and renders the output code for each:
229 * The HTML is accumulated in $this->HTMLcode
230 * Finishes off with a stopper-gif
231 *
232 * @return void
233 */
234 function generateList() {
235
236 // Set page record in header
237 $this->pageRecord = t3lib_BEfunc::getRecordWSOL('pages', $this->id);
238
239 // Traverse the TCA table array:
240 foreach ($GLOBALS['TCA'] as $tableName => $value) {
241
242 // Checking if the table should be rendered:
243 // Checks that we see only permitted/requested tables:
244 if ((!$this->table || $tableName == $this->table) && (!$this->tableList || t3lib_div::inList($this->tableList, $tableName)) && $GLOBALS['BE_USER']->check('tables_select', $tableName)) {
245
246 // Load full table definitions:
247 t3lib_div::loadTCA($tableName);
248
249 // Don't show table if hidden by TCA ctrl section
250 $hideTable = $GLOBALS['TCA'][$tableName]['ctrl']['hideTable'] ? TRUE : FALSE;
251 // Don't show table if hidden by pageTSconfig mod.web_list.hideTables
252 if (in_array($tableName, t3lib_div::trimExplode(',', $this->hideTables))) {
253 $hideTable = TRUE;
254 }
255 // Override previous selection if table is enabled or hidden by TSconfig TCA override mod.web_list.table
256 if (isset($this->tableTSconfigOverTCA[$tableName.'.']['hideTable'])) {
257 $hideTable = $this->tableTSconfigOverTCA[$tableName.'.']['hideTable'] ? TRUE : FALSE;
258 }
259 if ($hideTable) {
260 continue;
261 }
262
263 // iLimit is set depending on whether we're in single- or multi-table mode
264 if ($this->table) {
265 $this->iLimit= (isset($GLOBALS['TCA'][$tableName]['interface']['maxSingleDBListItems'])
266 ? intval($GLOBALS['TCA'][$tableName]['interface']['maxSingleDBListItems']) :
267 $this->itemsLimitSingleTable);
268 } else {
269 $this->iLimit = (isset($GLOBALS['TCA'][$tableName]['interface']['maxDBListItems'])
270 ? intval($GLOBALS['TCA'][$tableName]['interface']['maxDBListItems'])
271 : $this->itemsLimitPerTable);
272 }
273 if ($this->showLimit) {
274 $this->iLimit = $this->showLimit;
275 }
276
277 // Setting fields to select:
278 if ($this->allFields) {
279 $fields = $this->makeFieldList($tableName);
280 $fields[]='tstamp';
281 $fields[]='crdate';
282 $fields[]='_PATH_';
283 $fields[]='_CONTROL_';
284 if (is_array($this->setFields[$tableName])) {
285 $fields = array_intersect($fields, $this->setFields[$tableName]);
286 } else {
287 $fields = array();
288 }
289 } else {
290 $fields = array();
291 }
292
293 // Find ID to use (might be different for "versioning_followPages" tables)
294 if (intval($this->searchLevels) == 0) {
295 if ($GLOBALS['TCA'][$tableName]['ctrl']['versioning_followPages'] && $this->pageRecord['_ORIG_pid'] == -1
296 && $this->pageRecord['t3ver_swapmode'] == 0) {
297 $this->pidSelect = 'pid='.intval($this->pageRecord['_ORIG_uid']);
298 } else {
299 $this->pidSelect = 'pid='.intval($this->id);
300 }
301 }
302
303 // Finally, render the list:
304 $this->HTMLcode .= $this->getTable($tableName, $this->id, implode(',', $fields));
305 }
306 }
307 }
308
309 /**
310 * Creates the search box
311 *
312 * @param boolean $formFields If TRUE, the search box is wrapped in its own form-tags
313 * @return string HTML for the search box
314 */
315 function getSearchBox($formFields = 1) {
316
317 // Setting form-elements, if applicable:
318 $formElements = array('','');
319 if ($formFields) {
320 $formElements = array('<form action="' . htmlspecialchars($this->listURL('', -1, 'firstElementNumber')) . '" method="post">', '</form>');
321 }
322
323 // Make level selector:
324 $opt = array();
325 $parts = explode('|', $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.enterSearchLevels'));
326 foreach ($parts as $kv => $label) {
327 $opt[] = '<option value="'.$kv.'"'.($kv==intval($this->searchLevels)?' selected="selected"':'').'>'.htmlspecialchars($label).'</option>';
328 }
329 $lMenu = '<select name="search_levels">' . implode('', $opt) . '</select>';
330
331 // Table with the search box:
332 $content = '<div class="db_list-searchbox-form">
333 '.$formElements[0].'
334
335 <!--
336 Search box:
337 -->
338 <table border="0" cellpadding="0" cellspacing="0" id="typo3-dblist-search">
339 <tr>
340 <td><label for="search_field">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.enterSearchString', 1) . '</label></td>
341 <td><input type="text" name="search_field" id="search_field" value="' . htmlspecialchars($this->searchString) . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(10) . ' /></td>
342 <td>' . $lMenu . '</td>
343 <td><input type="submit" name="search" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.search', 1) . '" /></td>
344 </tr>
345 <tr>
346 <td><label for="showLimit">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showRecords', 1) . ':</label></td>
347 <td colspan="3"><input type="text" name="showLimit" id="showLimit" value="' . htmlspecialchars($this->showLimit ? $this->showLimit : '') . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' /></td>
348 </tr>
349 </table>
350 ' . $formElements[1] . '</div>';
351
352 return $content;
353 }
354
355 /**
356 * Creates the display of sys_notes for the page.
357 * Relies on the "sys_note" extension to be loaded.
358 *
359 * @return string HTML for the sys-notes (if any)
360 */
361 function showSysNotesForPage() {
362 $out = '';
363
364 // Checking if extension is loaded:
365 if (!t3lib_extMgm::isLoaded('sys_note')) {
366 return '';
367 }
368
369 // Create query for selecting the notes:
370 $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_note', 'pid IN (' . $this->id . ') AND (personal=0 OR cruser=' . intval($GLOBALS['BE_USER']->user['uid']) . ')' . t3lib_BEfunc::deleteClause('sys_note') . t3lib_BEfunc::versioningPlaceholderClause('sys_note'));
371
372 // Executing query:
373 $dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result);
374
375 // If some notes were found, render them:
376 if ($dbCount) {
377 $cat = array();
378
379 // Load full table description:
380 t3lib_div::loadTCA('sys_note');
381
382 // Traverse note-types and get labels:
383 if ($GLOBALS['TCA']['sys_note'] && $GLOBALS['TCA']['sys_note']['columns']['category']
384 && is_array($GLOBALS['TCA']['sys_note']['columns']['category']['config']['items'])) {
385 foreach($GLOBALS['TCA']['sys_note']['columns']['category']['config']['items'] as $el) {
386 $cat[$el[1]]=$GLOBALS['LANG']->sL($el[0]);
387 }
388 }
389
390 // For each note found, make rendering:
391 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
392
393 // Create content:
394 $iconImg = t3lib_iconWorks::getSpriteIconForRecord('sys_note', $row);
395 $subject = htmlspecialchars($row['subject']);
396 $fields = array();
397 $fields['Author:'] = htmlspecialchars($row['author'].($row['email'] && $row['author'] ? ', ':'').$row['email']);
398 $fields['Category:'] = htmlspecialchars($cat[$row['category']]);
399 $fields['Note:'] = nl2br(htmlspecialchars($row['message']));
400
401 // Compile content:
402 $out .= '
403
404
405 <!--
406 Sys-notes for list module:
407 -->
408 <table border="0" cellpadding="1" cellspacing="1" id="typo3-dblist-sysnotes">
409 <tr><td colspan="2" class="bgColor2">' . $iconImg . '<strong>' . $subject . '</strong></td></tr>
410 <tr><td class="bgColor4">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.category', 1) . '</td><td class="bgColor4">' . $fields['Category:'] . '</td></tr>
411 <tr><td class="bgColor4">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.author', 1) . '</td><td class="bgColor4">' . $fields['Author:'] . '</td></tr>
412 <tr><td class="bgColor4">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.note', 1) . '</td><td class="bgColor4">' . $fields['Note:'] . '</td></tr>
413 </table>
414 ';
415 }
416 }
417 return $out;
418 }
419
420 /******************************
421 *
422 * Various helper functions
423 *
424 ******************************/
425
426 /**
427 * Setting the field names to display in extended list.
428 * Sets the internal variable $this->setFields
429 *
430 * @return void
431 */
432 function setDispFields() {
433
434 // Getting from session:
435 $dispFields = $GLOBALS['BE_USER']->getModuleData('list/displayFields');
436
437 // If fields has been inputted, then set those as the value and push it to session variable:
438 if (is_array($this->displayFields)) {
439 reset($this->displayFields);
440 $tKey = key($this->displayFields);
441 $dispFields[$tKey] = $this->displayFields[$tKey];
442 $GLOBALS['BE_USER']->pushModuleData('list/displayFields', $dispFields);
443 }
444
445 // Setting result:
446 $this->setFields=$dispFields;
447 }
448
449 /**
450 * Create thumbnail code for record/field
451 *
452 * @param array $row Record array
453 * @param string $table Table (record is from)
454 * @param string $field Field name for which thumbsnail are to be rendered.
455 * @return string HTML for thumbnails, if any.
456 */
457 function thumbCode($row, $table, $field) {
458 return t3lib_BEfunc::thumbCode($row, $table, $field, $this->backPath);
459 }
460
461 /**
462 * Returns the SQL-query array to select the records from a table $table with pid = $id
463 *
464 * @param string $table Table name
465 * @param integer $id Page id (NOT USED! $this->pidSelect is used instead)
466 * @param string $addWhere Additional part for where clause
467 * @param string $fieldList Field list to select, * for all (for "SELECT [fieldlist] FROM ...")
468 * @return array Returns query array
469 */
470 function makeQueryArray($table, $id, $addWhere = '', $fieldList = '*') {
471 $hookObjectsArr = array();
472 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list.inc']['makeQueryArray'])) {
473 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list.inc']['makeQueryArray'] as $classRef) {
474 $hookObjectsArr[] = t3lib_div::getUserObj($classRef);
475 }
476 }
477
478 // Set ORDER BY:
479 $orderBy = ($GLOBALS['TCA'][$table]['ctrl']['sortby']
480 ? 'ORDER BY ' . $GLOBALS['TCA'][$table]['ctrl']['sortby']
481 : $GLOBALS['TCA'][$table]['ctrl']['default_sortby']);
482 if ($this->sortField) {
483 if (in_array($this->sortField, $this->makeFieldList($table, 1))) {
484 $orderBy = 'ORDER BY '.$this->sortField;
485 if ($this->sortRev) {
486 $orderBy .= ' DESC';
487 }
488 }
489 }
490
491 // Set LIMIT:
492 $limit = $this->iLimit ? ($this->firstElementNumber ? $this->firstElementNumber.',' : '').($this->iLimit+1) : '';
493
494 // Filtering on displayable pages (permissions):
495 $pC = ($table == 'pages' && $this->perms_clause)?' AND '.$this->perms_clause:'';
496
497 // Adding search constraints:
498 $search = $this->makeSearchString($table, $id);
499
500 // Compiling query array:
501 $queryParts = array(
502 'SELECT' => $fieldList,
503 'FROM' => $table,
504 'WHERE' => $this->pidSelect.
505 ' '.$pC.
506 t3lib_BEfunc::deleteClause($table).
507 t3lib_BEfunc::versioningPlaceholderClause($table).
508 ' '.$addWhere.
509 ' '.$search,
510 'GROUPBY' => '',
511 'ORDERBY' => $GLOBALS['TYPO3_DB']->stripOrderBy($orderBy),
512 'LIMIT' => $limit
513 );
514
515 // Filter out records that are translated, if TSconfig mod.web_list.hideTranslations is set
516 if ((in_array($table, t3lib_div::trimExplode(',', $this->hideTranslations)) || $this->hideTranslations === '*')
517 && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'])
518 && strcmp($table, 'pages_language_overlay')) {
519 $queryParts['WHERE'] .= ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . '=0 ';
520 }
521
522 // Apply hook as requested in http://bugs.typo3.org/view.php?id=4361
523 foreach ($hookObjectsArr as $hookObj) {
524 if (method_exists($hookObj, 'makeQueryArray_post')) {
525 $_params = array(
526 'orderBy' => $orderBy,
527 'limit' => $limit,
528 'pC' => $pC,
529 'search' => $search,
530 );
531 $hookObj->makeQueryArray_post($queryParts, $this, $table, $id, $addWhere, $fieldList, $_params);
532 }
533 }
534
535 // Return query:
536 return $queryParts;
537 }
538
539 /**
540 * Based on input query array (query for selecting count(*) from a table) it will select the number of records and set the value in $this->totalItems
541 *
542 * @param array $queryParts Query array
543 * @return void
544 * @see makeQueryArray()
545 */
546 function setTotalItems($queryParts) {
547 $this->totalItems = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
548 '*',
549 $queryParts['FROM'],
550 $queryParts['WHERE']
551 );
552 }
553
554 /**
555 * Creates part of query for searching after a word ($this->searchString)
556 * fields in input table.
557 *
558 * @param string $table Table, in which the fields are being searched.
559 * @param integer $currentPid Page id for the possible search limit. -1 only if called from an old XCLASS.
560 * @return string Returns part of WHERE-clause for searching, if applicable.
561 */
562 function makeSearchString($table, $currentPid = -1) {
563 $result = '';
564
565 $currentPid = intval($currentPid);
566 $tablePidField = ($table == 'pages' ? 'uid' : 'pid');
567
568 // Make query, only if table is valid and a search string is actually defined:
569 if ($this->searchString) {
570 $result = ' AND 0=1';
571 $searchableFields = $this->getSearchFields($table);
572 if (count($searchableFields) > 0) {
573 // Loading full table description - we need to traverse fields:
574 t3lib_div::loadTCA($table);
575
576 if (t3lib_utility_Math::canBeInterpretedAsInteger($this->searchString)) {
577 $whereParts = array(
578 'uid=' . $this->searchString
579 );
580
581 foreach ($searchableFields as $fieldName) {
582 if (isset($GLOBALS['TCA'][$table]['columns'][$fieldName])) {
583 $fieldConfig = &$GLOBALS['TCA'][$table]['columns'][$fieldName]['config'];
584 if ($fieldConfig['type'] == 'input' && $fieldConfig['eval'] && t3lib_div::inList($fieldConfig['eval'], 'int')) {
585 $condition = $fieldName . '=' . $this->searchString;
586 if (is_array($fieldConfig['search']) && in_array('pidonly', $fieldConfig['search']) && $currentPid > 0) {
587 $condition = '(' . $condition . ' AND ' . $tablePidField . '=' . $currentPid . ')';
588 }
589 $whereParts[] = $condition;
590 }
591 }
592 }
593 } else {
594 $whereParts = array();
595 $like = '\'%' .
596 $GLOBALS['TYPO3_DB']->quoteStr($GLOBALS['TYPO3_DB']->escapeStrForLike($this->searchString, $table), $table) .
597 '%\'';
598 foreach ($searchableFields as $fieldName) {
599 if (isset($GLOBALS['TCA'][$table]['columns'][$fieldName])) {
600 $fieldConfig = &$GLOBALS['TCA'][$table]['columns'][$fieldName]['config'];
601 $format = 'LCASE(%s) LIKE LCASE(%s)';
602 if (is_array($fieldConfig['search'])) {
603 if (in_array('case', $fieldConfig['search'])) {
604 $format = '%s LIKE %s';
605 }
606 if (in_array('pidonly', $fieldConfig['search']) && $currentPid > 0) {
607 $format = '(' . $format . ' AND ' . $tablePidField . '=' . $currentPid . ')';
608 }
609 if ($fieldConfig['search']['andWhere']) {
610 $format = '((' . $fieldConfig['search']['andWhere'] . ') AND (' . $format . '))';
611 }
612 }
613 if ($fieldConfig['type'] == 'text' ||
614 $fieldConfig['type'] == 'flex' ||
615 ($fieldConfig['type'] == 'input' && (!$fieldConfig['eval'] || !preg_match('/date|time|int/', $fieldConfig['eval'])))) {
616 $whereParts[] = sprintf($format, $fieldName, $like);
617 }
618 }
619 }
620 }
621
622 // If search-fields were defined (and there always are) we create the query:
623 if (count($whereParts)) {
624 $result = ' AND (' . implode(' OR ', $whereParts) . ')';
625 }
626 }
627 }
628 return $result;
629 }
630
631 /**
632 * Fetches a list of fields to use in the Backend search for the given table.
633 *
634 * @param string $tableName
635 * @return array
636 */
637 protected function getSearchFields($tableName) {
638 $fieldArray = array();
639 $fieldListWasSet = FALSE;
640
641 // Get fields from ctrl section of TCA first
642 if (isset($GLOBALS['TCA'][$tableName]['ctrl']['searchFields'])) {
643 $fieldArray = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$tableName]['ctrl']['searchFields'], TRUE);
644 $fieldListWasSet = TRUE;
645 }
646
647 // Call hook to add or change the list
648 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['mod_list']['getSearchFieldList'])) {
649 $hookParameters = array(
650 'tableHasSearchConfiguration' => $fieldListWasSet,
651 'tableName' => $tableName,
652 'searchFields' => &$fieldArray,
653 'searchString' => $this->searchString
654 );
655 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['mod_list']['getSearchFieldList'] as $hookFunction) {
656 t3lib_div::callUserFunction($hookFunction, $hookParameters, $this);
657 }
658 }
659
660 return $fieldArray;
661 }
662
663 /**
664 * Returns the title (based on $code) of a table ($table) with the proper link around. For headers over tables.
665 * The link will cause the display of all extended mode or not for the table.
666 *
667 * @param string $table Table name
668 * @param string $code Table label
669 * @return string The linked table label
670 */
671 function linkWrapTable($table, $code) {
672 if ($this->table != $table) {
673 return '<a href="' . htmlspecialchars($this->listURL('', $table, 'firstElementNumber')) . '">' . $code . '</a>';
674 } else {
675 return '<a href="' . htmlspecialchars($this->listURL('', '', 'sortField,sortRev,table,firstElementNumber')) . '">' . $code . '</a>';
676 }
677 }
678
679 /**
680 * Returns the title (based on $code) of a record (from table $table) with the proper link around (that is for 'pages'-records a link to the level of that record...)
681 *
682 * @param string $table Table name
683 * @param integer $uid Item uid
684 * @param string $code Item title (not htmlspecialchars()'ed yet)
685 * @param array $row Item row
686 * @return string The item title. Ready for HTML output (is htmlspecialchars()'ed)
687 */
688 function linkWrapItems($table, $uid, $code, $row) {
689 $origCode = $code;
690
691 // If the title is blank, make a "no title" label:
692 if (!strcmp($code, '')) {
693 $code = '<i>[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.no_title', 1) . ']</i> - ' . htmlspecialchars(t3lib_div::fixed_lgd_cs(t3lib_BEfunc::getRecordTitle($table, $row), $GLOBALS['BE_USER']->uc['titleLen']));
694 } else {
695 $code = htmlspecialchars(t3lib_div::fixed_lgd_cs($code, $this->fixedL));
696 if ($code != htmlspecialchars($origCode)) {
697 $code = '<span title="'.htmlspecialchars($origCode).'">'.$code.'</span>';
698 }
699 }
700
701 switch((string)$this->clickTitleMode) {
702 case 'edit':
703 // If the listed table is 'pages' we have to request the permission settings for each page:
704 if ($table == 'pages') {
705 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages', $row['uid']));
706 $permsEdit = $localCalcPerms&2;
707 } else {
708 $permsEdit = $this->calcPerms&16;
709 }
710
711 // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
712 if ($permsEdit) {
713 $params = '&edit['.$table.']['.$row['uid'].']=edit';
714 $code = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::editOnClick($params, $this->backPath, -1)) .
715 '" title="' . $GLOBALS['LANG']->getLL('edit', 1) . '">' .
716 $code .
717 '</a>';
718 }
719 break;
720 case 'show':
721 // "Show" link (only pages and tt_content elements)
722 if ($table == 'pages' || $table == 'tt_content') {
723 $code = '<a href="#" onclick="'. htmlspecialchars(t3lib_BEfunc::viewOnClick(
724 $table == 'tt_content' ? $this->id . '#' . $row['uid'] : $row['uid'])
725 ) . '" title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', 1) . '">'.
726 $code. '</a>';
727 }
728 break;
729 case 'info':
730 // "Info": (All records)
731 $code = '<a href="#" onclick="'.htmlspecialchars('top.launchView(\'' . $table . '\', \'' . $row['uid'] .
732 '\'); return false;') . '" title="'.$GLOBALS['LANG']->getLL('showInfo', 1) . '">' .
733 $code.
734 '</a>';
735 break;
736 default:
737 // Output the label now:
738 if ($table == 'pages') {
739 $code = '<a href="' . htmlspecialchars($this->listURL($uid, '', 'firstElementNumber')) . '" onclick="setHighlight(' . $uid . ')">' . $code . '</a>';
740 } else {
741 $code = $this->linkUrlMail($code, $origCode);
742 }
743 break;
744 }
745
746 return $code;
747 }
748
749 /**
750 * Wrapping input code in link to URL or email if $testString is either.
751 *
752 * @param string $code code to wrap
753 * @param string $testString String which is tested for being a URL or email and which will be used for the link if so.
754 * @return string Link-Wrapped $code value, if $testString was URL or email.
755 */
756 function linkUrlMail($code, $testString) {
757
758 // Check for URL:
759 $schema = parse_url($testString);
760 if ($schema['scheme'] && t3lib_div::inList('http,https,ftp', $schema['scheme'])) {
761 return '<a href="'.htmlspecialchars($testString).'" target="_blank">'.$code.'</a>';
762 }
763
764 // Check for email:
765 if (t3lib_div::validEmail($testString)) {
766 return '<a href="mailto:'.htmlspecialchars($testString).'" target="_blank">'.$code.'</a>';
767 }
768
769 // Return if nothing else...
770 return $code;
771 }
772
773 /**
774 * Creates the URL to this script, including all relevant GPvars
775 * Fixed GPvars are id, table, imagemode, returlUrl, search_field, search_levels and showLimit
776 * The GPvars "sortField" and "sortRev" are also included UNLESS they are found in the $exclList variable.
777 *
778 * @param string $altId Alternative id value. Enter blank string for the current id ($this->id)
779 * @param string $table Tablename to display. Enter "-1" for the current table.
780 * @param string $exclList Commalist of fields NOT to include ("sortField", "sortRev" or "firstElementNumber")
781 * @return string URL
782 */
783 function listURL($altId = '', $table = -1, $exclList = '') {
784 $urlParameters = array();
785 if (strcmp($altId, '')) {
786 $urlParameters['id'] = $altId;
787 } else {
788 $urlParameters['id'] = $this->id;
789 }
790 if ($table === -1) {
791 $urlParameters['table'] = $this->table;
792 } else {
793 $urlParameters['table'] = $table;
794 }
795 if ($this->thumbs) {
796 $urlParameters['imagemode'] = $this->thumbs;
797 }
798 if ($this->returnUrl) {
799 $urlParameters['returnUrl'] = $this->returnUrl;
800 }
801 if ($this->searchString) {
802 $urlParameters['search_field'] = $this->searchString;
803 }
804 if ($this->searchLevels) {
805 $urlParameters['search_levels'] = $this->searchLevels;
806 }
807 if ($this->showLimit) {
808 $urlParameters['showLimit'] = $this->showLimit;
809 }
810 if ((!$exclList || !t3lib_div::inList($exclList, 'firstElementNumber')) && $this->firstElementNumber) {
811 $urlParameters['pointer'] = $this->firstElementNumber;
812 }
813 if ((!$exclList || !t3lib_div::inList($exclList, 'sortField')) && $this->sortField) {
814 $urlParameters['sortField'] = $this->sortField;
815 }
816 if ((!$exclList || !t3lib_div::inList($exclList, 'sortRev')) && $this->sortRev) {
817 $urlParameters['sortRev'] = $this->sortRev;
818 }
819
820 return t3lib_BEfunc::getModuleUrl('web_list', $urlParameters);
821 }
822
823 /**
824 * Returns "requestUri" - which is basically listURL
825 *
826 * @return string Content of ->listURL()
827 */
828 function requestUri() {
829 return $this->listURL();
830 }
831
832 /**
833 * Makes the list of fields to select for a table
834 *
835 * @param string $table Table name
836 * @param boolean $dontCheckUser If set, users access to the field (non-exclude-fields) is NOT checked.
837 * @param boolean $addDateFields If set, also adds crdate and tstamp fields (note: they will also be added if user is admin or dontCheckUser is set)
838 * @return array Array, where values are fieldnames to include in query
839 */
840 function makeFieldList($table, $dontCheckUser = 0, $addDateFields = 0) {
841
842 // Init fieldlist array:
843 $fieldListArr = array();
844
845 // Check table:
846 if (is_array($GLOBALS['TCA'][$table])
847 && isset($GLOBALS['TCA'][$table]['columns'])
848 && is_array($GLOBALS['TCA'][$table]['columns'])
849 ) {
850 t3lib_div::loadTCA($table);
851
852 if (isset($GLOBALS['TCA'][$table]['columns']) && is_array($GLOBALS['TCA'][$table]['columns'])) {
853 // Traverse configured columns and add them to field array, if available for user.
854 foreach ($GLOBALS['TCA'][$table]['columns'] as $fN => $fieldValue) {
855 if ($dontCheckUser ||
856 ((!$fieldValue['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $fN))
857 && $fieldValue['config']['type']!='passthrough')) {
858 $fieldListArr[]=$fN;
859 }
860 }
861
862 // Add special fields:
863 if ($dontCheckUser || $GLOBALS['BE_USER']->isAdmin()) {
864 $fieldListArr[] = 'uid';
865 $fieldListArr[] = 'pid';
866 }
867
868 // Add date fields
869 if ($dontCheckUser || $GLOBALS['BE_USER']->isAdmin() || $addDateFields) {
870 if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
871 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
872 }
873 if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
874 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['crdate'];
875 }
876 }
877
878 // Add more special fields:
879 if ($dontCheckUser || $GLOBALS['BE_USER']->isAdmin()) {
880 if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {
881 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['cruser_id'];
882 }
883 if ($GLOBALS['TCA'][$table]['ctrl']['sortby']) {
884 $fieldListArr[] = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
885 }
886 if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
887 $fieldListArr[] = 't3ver_id';
888 $fieldListArr[] = 't3ver_state';
889 $fieldListArr[] = 't3ver_wsid';
890 if ($table === 'pages') {
891 $fieldListArr[] = 't3ver_swapmode';
892 }
893 }
894 }
895 } else {
896 t3lib_div::sysLog(
897 sprintf('$TCA is broken for the table "%s": no required "columns" entry in $TCA.', $table),
898 'core',
899 t3lib_div::SYSLOG_SEVERITY_ERROR
900 );
901 }
902 }
903 return $fieldListArr;
904 }
905
906 /**
907 * Creates an instance of t3lib_pageTree which will select a page tree to $depth and return the object. In that object we will find the ids of the tree.
908 *
909 * @param integer $id Page id.
910 * @param integer $depth Depth to go down.
911 * @param string $perms_clause Select clause
912 * @return object t3lib_pageTree instance with created list of ids.
913 */
914 function getTreeObject($id, $depth, $perms_clause) {
915 $tree = t3lib_div::makeInstance('t3lib_pageTree');
916 $tree->init('AND '.$perms_clause);
917 $tree->makeHTML = 0;
918 $tree->fieldArray = array('uid', 'php_tree_stop');
919 if ($depth) {
920 $tree->getTree($id, $depth, '');
921 }
922 $tree->ids[] = $id;
923 return $tree;
924 }
925
926 /**
927 * Redirects to TCEforms (alt_doc) if a record is just localized.
928 *
929 * @param string $justLocalized String with table, orig uid and language separated by ":"
930 * @return void
931 */
932 function localizationRedirect($justLocalized) {
933 list($table,$orig_uid,$language) = explode(':', $justLocalized);
934
935 if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField']
936 && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) {
937 $localizedRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
938 'uid',
939 $table,
940 $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '=' . intval($language) . ' AND ' .
941 $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . '=' . intval($orig_uid) .
942 t3lib_BEfunc::deleteClause($table).
943 t3lib_BEfunc::versioningPlaceholderClause($table)
944 );
945
946 if (is_array($localizedRecord)) {
947 // Create parameters and finally run the classic page module for creating a new page translation
948 $url = substr($this->listURL(), strlen($this->backPath));
949 $params = '&edit['.$table.']['.$localizedRecord['uid'].']=edit';
950 $returnUrl = '&returnUrl='.rawurlencode($url);
951 $location = $GLOBALS['BACK_PATH'].'alt_doc.php?'.$params.$returnUrl;
952
953 t3lib_utility_Http::redirect($location);
954 }
955 }
956 }
957 }
958 ?>