a83c721c6c7f58b3e68be6474a68754e29cf4504
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Database / QueryView.php
1 <?php
2 namespace TYPO3\CMS\Core\Database;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19
20 /**
21 * Class used in module tools/dbint (advanced search) and which may hold code specific for that module
22 * However the class has a general principle in it which may be used in the web/export module.
23 *
24 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
25 * @author Jo Hasenau <info@cybercraft.de>
26 */
27 class QueryView {
28
29 /**
30 * @var string
31 */
32 public $storeList = 'search_query_smallparts,search_result_labels,labels_noprefix,show_deleted,queryConfig,queryTable,queryFields,queryLimit,queryOrder,queryOrderDesc,queryOrder2,queryOrder2Desc,queryGroup,search_query_makeQuery';
33
34 /**
35 * @var string
36 */
37 public $downloadScript = 'index.php';
38
39 /**
40 * @var int
41 */
42 public $formW = 48;
43
44 /**
45 * @var int
46 */
47 public $noDownloadB = 0;
48
49 /**
50 * @var array
51 */
52 public $hookArray = array();
53
54 /**
55 * @var string
56 */
57 protected $formName = '';
58
59 /**
60 * constructor
61 */
62 public function __construct() {
63 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_t3lib_fullsearch.xlf');
64 }
65
66 /**
67 * Get form
68 *
69 * @return string
70 */
71 public function form() {
72 $out = '
73 Search Word:<BR>
74 <input type="search" name="SET[sword]" value="' . htmlspecialchars($GLOBALS['SOBE']->MOD_SETTINGS['sword']) . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(20) . '>
75 <input class="btn btn-default" type="submit" name="submit" value="Search All Records">
76 ';
77 return $out;
78 }
79
80 /**
81 * Make store control
82 *
83 * @return string
84 */
85 public function makeStoreControl() {
86 // Load/Save
87 $storeArray = $this->initStoreArray();
88 // Store Array:
89 $opt = array();
90 foreach ($storeArray as $k => $v) {
91 $opt[] = '<option value="' . $k . '">' . htmlspecialchars($v) . '</option>';
92 }
93 // Actions:
94 if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('sys_action') && $GLOBALS['BE_USER']->isAdmin()) {
95 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_action', 'type=2', '', 'title');
96 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
97 $opt[] = '<option value="0">__Save to Action:__</option>';
98 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
99 $opt[] = '<option value="-' . $row['uid'] . '">' . htmlspecialchars(($row['title'] . ' [' . $row['uid'] . ']')) . '</option>';
100 }
101 }
102 $GLOBALS['TYPO3_DB']->sql_free_result($res);
103 }
104 $TDparams = ' nowrap="nowrap" class="bgColor4"';
105 $tmpCode = '
106 <table border="0" cellpadding="3" cellspacing="1">
107 <tr' . $TDparams . '>
108 <td>
109 <select name="storeControl[STORE]" onChange="document.forms[0][\'storeControl[title]\'].value= this.options[this.selectedIndex].value!=0 ? this.options[this.selectedIndex].text : \'\';">' . implode(LF, $opt) . '</select>
110 <input class="btn btn-default" type="submit" name="storeControl[LOAD]" value="Load">
111 </td>
112 </tr>
113 <tr' . $TDparams . '>
114 <td nowrap>
115 <input name="storeControl[title]" value="" type="text" max="80"' . $GLOBALS['SOBE']->doc->formWidth() . '>
116 <input class="btn btn-default" type="submit" name="storeControl[SAVE]" value="Save" onClick="if (document.forms[0][\'storeControl[STORE]\'].options[document.forms[0][\'storeControl[STORE]\'].selectedIndex].value<0) return confirm(\'Are you sure you want to overwrite the existing query in this action?\');">
117 <input class="btn btn-default" type="submit" name="storeControl[REMOVE]" value="Remove">
118 </td>
119 </tr>
120 </table>
121 ';
122 return $tmpCode;
123 }
124
125 /**
126 * Init store array
127 *
128 * @return array
129 */
130 public function initStoreArray() {
131 $storeArray = array(
132 '0' => '[New]'
133 );
134 $savedStoreArray = unserialize($GLOBALS['SOBE']->MOD_SETTINGS['storeArray']);
135 if (is_array($savedStoreArray)) {
136 $storeArray = array_merge($storeArray, $savedStoreArray);
137 }
138 return $storeArray;
139 }
140
141 /**
142 * Clean store query configs
143 *
144 * @param array $storeQueryConfigs
145 * @param array $storeArray
146 * @return array
147 */
148 public function cleanStoreQueryConfigs($storeQueryConfigs, $storeArray) {
149 if (is_array($storeQueryConfigs)) {
150 foreach ($storeQueryConfigs as $k => $v) {
151 if (!isset($storeArray[$k])) {
152 unset($storeQueryConfigs[$k]);
153 }
154 }
155 }
156 return $storeQueryConfigs;
157 }
158
159 /**
160 * Add to store query configs
161 *
162 * @param array $storeQueryConfigs
163 * @param int $index
164 * @return array
165 */
166 public function addToStoreQueryConfigs($storeQueryConfigs, $index) {
167 $keyArr = explode(',', $this->storeList);
168 $storeQueryConfigs[$index] = array();
169 foreach ($keyArr as $k) {
170 $storeQueryConfigs[$index][$k] = $GLOBALS['SOBE']->MOD_SETTINGS[$k];
171 }
172 return $storeQueryConfigs;
173 }
174
175 /**
176 * Save query in action
177 *
178 * @param int $uid
179 * @return int
180 */
181 public function saveQueryInAction($uid) {
182 if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('sys_action')) {
183 $keyArr = explode(',', $this->storeList);
184 $saveArr = array();
185 foreach ($keyArr as $k) {
186 $saveArr[$k] = $GLOBALS['SOBE']->MOD_SETTINGS[$k];
187 }
188 $qOK = 0;
189 // Show query
190 if ($saveArr['queryTable']) {
191 /** @var \TYPO3\CMS\Core\Database\QueryGenerator */
192 $qGen = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\QueryGenerator::class);
193 $qGen->init('queryConfig', $saveArr['queryTable']);
194 $qGen->makeSelectorTable($saveArr);
195 $qGen->enablePrefix = 1;
196 $qString = $qGen->getQuery($qGen->queryConfig);
197 $qCount = $GLOBALS['TYPO3_DB']->SELECTquery('count(*)', $qGen->table, $qString . BackendUtility::deleteClause($qGen->table));
198 $qSelect = $qGen->getSelectQuery($qString);
199 $res = @$GLOBALS['TYPO3_DB']->sql_query($qCount);
200 if (!$GLOBALS['TYPO3_DB']->sql_error()) {
201 $GLOBALS['TYPO3_DB']->sql_free_result($res);
202 $dA = array();
203 $dA['t2_data'] = serialize(array(
204 'qC' => $saveArr,
205 'qCount' => $qCount,
206 'qSelect' => $qSelect,
207 'qString' => $qString
208 ));
209 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_action', 'uid=' . (int)$uid, $dA);
210 $qOK = 1;
211 }
212 }
213 return $qOK;
214 }
215 }
216
217 /**
218 * Load store query configs
219 *
220 * @param array $storeQueryConfigs
221 * @param int $storeIndex
222 * @param array $writeArray
223 * @return array
224 */
225 public function loadStoreQueryConfigs($storeQueryConfigs, $storeIndex, $writeArray) {
226 if ($storeQueryConfigs[$storeIndex]) {
227 $keyArr = explode(',', $this->storeList);
228 foreach ($keyArr as $k) {
229 $writeArray[$k] = $storeQueryConfigs[$storeIndex][$k];
230 }
231 }
232 return $writeArray;
233 }
234
235 /**
236 * Process store control
237 *
238 * @return string
239 */
240 public function procesStoreControl() {
241 $storeArray = $this->initStoreArray();
242 $storeQueryConfigs = unserialize($GLOBALS['SOBE']->MOD_SETTINGS['storeQueryConfigs']);
243 $storeControl = GeneralUtility::_GP('storeControl');
244 $storeIndex = (int)$storeControl['STORE'];
245 $saveStoreArray = 0;
246 $writeArray = array();
247 if (is_array($storeControl)) {
248 $msg = '';
249 if ($storeControl['LOAD']) {
250 if ($storeIndex > 0) {
251 $writeArray = $this->loadStoreQueryConfigs($storeQueryConfigs, $storeIndex, $writeArray);
252 $saveStoreArray = 1;
253 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, sprintf($GLOBALS['LANG']->getLL('query_loaded'), htmlspecialchars($storeArray[$storeIndex])));
254 } elseif ($storeIndex < 0 && \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('sys_action')) {
255 $actionRecord = BackendUtility::getRecord('sys_action', abs($storeIndex));
256 if (is_array($actionRecord)) {
257 $dA = unserialize($actionRecord['t2_data']);
258 $dbSC = array();
259 if (is_array($dA['qC'])) {
260 $dbSC[0] = $dA['qC'];
261 }
262 $writeArray = $this->loadStoreQueryConfigs($dbSC, '0', $writeArray);
263 $saveStoreArray = 1;
264 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, sprintf($GLOBALS['LANG']->getLL('query_from_action_loaded'), htmlspecialchars($actionRecord['title'])));
265 }
266 }
267 } elseif ($storeControl['SAVE']) {
268 if ($storeIndex < 0) {
269 $qOK = $this->saveQueryInAction(abs($storeIndex));
270 if ($qOK) {
271 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $GLOBALS['LANG']->getLL('query_saved'));
272 } else {
273 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $GLOBALS['LANG']->getLL('query_notsaved'), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
274 }
275 } else {
276 if (trim($storeControl['title'])) {
277 if ($storeIndex > 0) {
278 $storeArray[$storeIndex] = $storeControl['title'];
279 } else {
280 $storeArray[] = $storeControl['title'];
281 end($storeArray);
282 $storeIndex = key($storeArray);
283 }
284 $storeQueryConfigs = $this->addToStoreQueryConfigs($storeQueryConfigs, $storeIndex);
285 $saveStoreArray = 1;
286 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $GLOBALS['LANG']->getLL('query_saved'));
287 }
288 }
289 } elseif ($storeControl['REMOVE']) {
290 if ($storeIndex > 0) {
291 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, sprintf($GLOBALS['LANG']->getLL('query_removed'), htmlspecialchars($storeArray[$storeControl['STORE']])));
292 // Removing
293 unset($storeArray[$storeControl['STORE']]);
294 $saveStoreArray = 1;
295 }
296 }
297 if ($flashMessage) {
298 $msg = $flashMessage->render();
299 }
300 }
301 if ($saveStoreArray) {
302 // Making sure, index 0 is not set!
303 unset($storeArray[0]);
304 $writeArray['storeArray'] = serialize($storeArray);
305 $writeArray['storeQueryConfigs'] = serialize($this->cleanStoreQueryConfigs($storeQueryConfigs, $storeArray));
306 $GLOBALS['SOBE']->MOD_SETTINGS = BackendUtility::getModuleData($GLOBALS['SOBE']->MOD_MENU, $writeArray, $GLOBALS['SOBE']->MCONF['name'], 'ses');
307 }
308 return $msg;
309 }
310
311 /**
312 * Query marker
313 *
314 * @return string
315 */
316 public function queryMaker() {
317 $output = '';
318 if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3lib_fullsearch'])) {
319 $this->hookArray = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3lib_fullsearch'];
320 }
321 $msg = $this->procesStoreControl();
322 if (!$GLOBALS['BE_USER']->userTS['mod.']['dbint.']['disableStoreControl']) {
323 $output .= $GLOBALS['SOBE']->doc->section('Load/Save Query', $this->makeStoreControl(), 0, 1);
324 if ($msg) {
325 $output .= '<br />' . $msg;
326 }
327 $output .= $GLOBALS['SOBE']->doc->spacer(20);
328 }
329 // Query Maker:
330 $qGen = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\QueryGenerator::class);
331 $qGen->init('queryConfig', $GLOBALS['SOBE']->MOD_SETTINGS['queryTable']);
332 if ($this->formName) {
333 $qGen->setFormName($this->formName);
334 }
335 $tmpCode = $qGen->makeSelectorTable($GLOBALS['SOBE']->MOD_SETTINGS);
336 $output .= $GLOBALS['SOBE']->doc->section('Make query', $tmpCode, 0, 1);
337 $mQ = $GLOBALS['SOBE']->MOD_SETTINGS['search_query_makeQuery'];
338 // Make form elements:
339 if ($qGen->table && is_array($GLOBALS['TCA'][$qGen->table])) {
340 if ($mQ) {
341 // Show query
342 $qGen->enablePrefix = 1;
343 $qString = $qGen->getQuery($qGen->queryConfig);
344 switch ($mQ) {
345 case 'count':
346 $qExplain = $GLOBALS['TYPO3_DB']->SELECTquery('count(*)', $qGen->table, $qString . BackendUtility::deleteClause($qGen->table));
347 break;
348 default:
349 $qExplain = $qGen->getSelectQuery($qString);
350 if ($mQ == 'explain') {
351 $qExplain = 'EXPLAIN ' . $qExplain;
352 }
353 }
354 if (!$GLOBALS['BE_USER']->userTS['mod.']['dbint.']['disableShowSQLQuery']) {
355 $output .= $GLOBALS['SOBE']->doc->section('SQL query', $this->tableWrap(htmlspecialchars($qExplain)), 0, 1);
356 }
357 $res = @$GLOBALS['TYPO3_DB']->sql_query($qExplain);
358 if ($GLOBALS['TYPO3_DB']->sql_error()) {
359 $out = '<BR><strong>Error:</strong><BR><font color="red"><strong>' . $GLOBALS['TYPO3_DB']->sql_error() . '</strong></font>';
360 $output .= $GLOBALS['SOBE']->doc->section('SQL error', $out, 0, 1);
361 } else {
362 $cPR = $this->getQueryResultCode($mQ, $res, $qGen->table);
363 $GLOBALS['TYPO3_DB']->sql_free_result($res);
364 $output .= $GLOBALS['SOBE']->doc->section($cPR['header'], $cPR['content'], 0, 1);
365 }
366 }
367 }
368 return $output;
369 }
370
371 /**
372 * Get query result code
373 *
374 * @param string $mQ
375 * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
376 * @param string $table
377 * @return string
378 */
379 public function getQueryResultCode($mQ, $res, $table) {
380 $out = '';
381 $cPR = array();
382 switch ($mQ) {
383 case 'count':
384 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
385 $cPR['header'] = 'Count';
386 $cPR['content'] = '<BR><strong>' . $row[0] . '</strong> records selected.';
387 break;
388 case 'all':
389 $rowArr = array();
390 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
391 $rowArr[] = $this->resultRowDisplay($row, $GLOBALS['TCA'][$table], $table);
392 $lrow = $row;
393 }
394 if (is_array($this->hookArray['beforeResultTable'])) {
395 foreach ($this->hookArray['beforeResultTable'] as $_funcRef) {
396 $out .= GeneralUtility::callUserFunction($_funcRef, $GLOBALS['SOBE']->MOD_SETTINGS, $this);
397 }
398 }
399 if (count($rowArr)) {
400 $out .= '<table border="0" cellpadding="2" cellspacing="1" width="100%">' . $this->resultRowTitles($lrow, $GLOBALS['TCA'][$table], $table) . implode(LF, $rowArr) . '</table>';
401 }
402 if (!$out) {
403 $out = '<em>No rows selected!</em>';
404 }
405 $cPR['header'] = 'Result';
406 $cPR['content'] = $out;
407 break;
408 case 'csv':
409 $rowArr = array();
410 $first = 1;
411 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
412 if ($first) {
413 $rowArr[] = $this->csvValues(array_keys($row), ',', '');
414 $first = 0;
415 }
416 $rowArr[] = $this->csvValues($row, ',', '"', $GLOBALS['TCA'][$table], $table);
417 }
418 if (count($rowArr)) {
419 $out .= '<textarea name="whatever" rows="20" wrap="off"' . $GLOBALS['SOBE']->doc->formWidthText($this->formW, '', 'off') . ' class="fixed-font">' . GeneralUtility::formatForTextarea(implode(LF, $rowArr)) . '</textarea>';
420 if (!$this->noDownloadB) {
421 $out .= '<br><input class="btn btn-default" type="submit" name="download_file" value="Click to download file" onClick="window.location.href=\'' . $this->downloadScript . '\';">';
422 }
423 // Downloads file:
424 if (GeneralUtility::_GP('download_file')) {
425 $filename = 'TYPO3_' . $table . '_export_' . date('dmy-Hi') . '.csv';
426 $mimeType = 'application/octet-stream';
427 header('Content-Type: ' . $mimeType);
428 header('Content-Disposition: attachment; filename=' . $filename);
429 echo implode(CRLF, $rowArr);
430 die;
431 }
432 }
433 if (!$out) {
434 $out = '<em>No rows selected!</em>';
435 }
436 $cPR['header'] = 'Result';
437 $cPR['content'] = $out;
438 break;
439 case 'explain':
440
441 default:
442 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
443 $out .= '<br />' . \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($row);
444 }
445 $cPR['header'] = 'Explain SQL query';
446 $cPR['content'] = $out;
447 }
448 return $cPR;
449 }
450
451 /**
452 * CSV values
453 *
454 * @param array $row
455 * @param string $delim
456 * @param string $quote
457 * @param array $conf
458 * @param string $table
459 * @return string A single line of CSV
460 */
461 public function csvValues($row, $delim = ',', $quote = '"', $conf = array(), $table = '') {
462 $valueArray = $row;
463 if ($GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels'] && $table) {
464 foreach ($valueArray as $key => $val) {
465 $valueArray[$key] = $this->getProcessedValueExtra($table, $key, $val, $conf, ';');
466 }
467 }
468 return GeneralUtility::csvValues($valueArray, $delim, $quote);
469 }
470
471 /**
472 * Table wrap
473 *
474 * @param string $str
475 * @return string
476 */
477 public function tableWrap($str) {
478 return '<table border="0" cellpadding="10" cellspacing="0" class="bgColor4"><tr><td nowrap><pre>' . $str . '</pre></td></tr></table>';
479 }
480
481 /**
482 * Search
483 *
484 * @return string
485 */
486 public function search() {
487 $SET = $GLOBALS['SOBE']->MOD_SETTINGS;
488 $swords = $SET['sword'];
489 $out = '';
490 $limit = 200;
491 $showAlways = 0;
492 if ($swords) {
493 foreach ($GLOBALS['TCA'] as $table => $value) {
494 // Get fields list
495 $conf = $GLOBALS['TCA'][$table];
496 // Avoid querying tables with no columns
497 if (empty($conf['columns'])) {
498 continue;
499 }
500 $fieldsInDatabase = $GLOBALS['TYPO3_DB']->admin_get_fields($table);
501 $list = array_intersect(array_keys($conf['columns']), array_keys($fieldsInDatabase));
502 // Get query
503 $qp = $GLOBALS['TYPO3_DB']->searchQuery(array($swords), $list, $table);
504 // Count:
505 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', $table, $qp . BackendUtility::deleteClause($table));
506 if ($count || $showAlways) {
507 // Output header:
508 $out .= '<strong>TABLE:</strong> ' . $GLOBALS['LANG']->sL($conf['ctrl']['title']) . '<BR>';
509 $out .= '<strong>Results:</strong> ' . $count . '<BR>';
510 // Show to limit
511 if ($count) {
512 $rowArr = array();
513 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,' . $conf['ctrl']['label'], $table, $qp . BackendUtility::deleteClause($table), '', '', $limit);
514 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
515 $rowArr[] = $this->resultRowDisplay($row, $conf, $table);
516 $lrow = $row;
517 }
518 $GLOBALS['TYPO3_DB']->sql_free_result($res);
519 $out .= '<table border="0" cellpadding="2" cellspacing="1">' . $this->resultRowTitles($lrow, $conf, $table) . implode(LF, $rowArr) . '</table>';
520 }
521 $out .= '<HR>';
522 }
523 }
524 }
525 return $out;
526 }
527
528 /**
529 * Result row display
530 *
531 * @param array $row
532 * @param array $conf
533 * @param string $table
534 * @return string
535 */
536 public function resultRowDisplay($row, $conf, $table) {
537 static $even = FALSE;
538 $tce = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
539 $SET = $GLOBALS['SOBE']->MOD_SETTINGS;
540 $out = '<tr class="bgColor' . ($even ? '6' : '4') . '">';
541 $even = !$even;
542 foreach ($row as $fieldName => $fieldValue) {
543 if (GeneralUtility::inList($SET['queryFields'], $fieldName) || !$SET['queryFields'] && $fieldName != 'pid' && $fieldName != 'deleted') {
544 if ($SET['search_result_labels']) {
545 $fVnew = $this->getProcessedValueExtra($table, $fieldName, $fieldValue, $conf, '<br />');
546 } else {
547 $fVnew = htmlspecialchars($fieldValue);
548 }
549 $out .= '<td>' . $fVnew . '</td>';
550 }
551 }
552 $params = '&edit[' . $table . '][' . $row['uid'] . ']=edit';
553 $out .= '<td nowrap>';
554 if (!$row['deleted']) {
555 $out .= '<a href="#" onClick="top.launchView(\'' . $table . '\',' . $row['uid'] . ',\'' . $GLOBALS['BACK_PATH'] . '\');return false;">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-dialog-information') . '</a>';
556 $out .= '<a href="#" onClick="' . BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'], (GeneralUtility::getIndpEnv('REQUEST_URI') . GeneralUtility::implodeArrayForUrl('SET', (array)GeneralUtility::_POST('SET')))) . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-open') . '</a>';
557 } else {
558 $out .= '<a href="' . GeneralUtility::linkThisUrl(($GLOBALS['BACK_PATH'] . 'tce_db.php'), array(
559 ('cmd[' . $table . '][' . $row['uid'] . '][undelete]') => '1',
560 'redirect' => GeneralUtility::linkThisScript(array())
561 )) . BackendUtility::getUrlToken('tceAction') . '">';
562 $out .= \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-restore', array('title' => 'undelete only')) . '</a>';
563 $out .= '<a href="' . GeneralUtility::linkThisUrl(($GLOBALS['BACK_PATH'] . 'tce_db.php'), array(
564 ('cmd[' . $table . '][' . $row['uid'] . '][undelete]') => '1',
565 'redirect' => GeneralUtility::linkThisUrl('alt_doc.php', array(
566 ('edit[' . $table . '][' . $row['uid'] . ']') => 'edit',
567 'returnUrl' => GeneralUtility::linkThisScript(array())
568 ))
569 )) . BackendUtility::getUrlToken('tceAction') . '">';
570 $out .= \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-restore-edit', array('title' => 'undelete and edit')) . '</a>';
571 }
572 $_params = array($table => $row);
573 if (is_array($this->hookArray['additionalButtons'])) {
574 foreach ($this->hookArray['additionalButtons'] as $_funcRef) {
575 $out .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
576 }
577 }
578 $out .= '</td>
579 </tr>
580 ';
581 return $out;
582 }
583
584 /**
585 * Get processed value extra
586 *
587 * @param string $table
588 * @param string $fieldName
589 * @param string $fieldValue
590 * @param array $conf Not used
591 * @param string $splitString
592 * @return string
593 */
594 public function getProcessedValueExtra($table, $fieldName, $fieldValue, $conf, $splitString) {
595 $out = '';
596 // Analysing the fields in the table.
597 if (is_array($GLOBALS['TCA'][$table])) {
598 $fC = $GLOBALS['TCA'][$table]['columns'][$fieldName];
599 $fields = $fC['config'];
600 $fields['exclude'] = $fC['exclude'];
601 if (is_array($fC) && $fC['label']) {
602 $fields['label'] = preg_replace('/:$/', '', trim($GLOBALS['LANG']->sL($fC['label'])));
603 switch ($fields['type']) {
604 case 'input':
605 if (preg_match('/int|year/i', $fields['eval'])) {
606 $fields['type'] = 'number';
607 } elseif (preg_match('/time/i', $fields['eval'])) {
608 $fields['type'] = 'time';
609 } elseif (preg_match('/date/i', $fields['eval'])) {
610 $fields['type'] = 'date';
611 } else {
612 $fields['type'] = 'text';
613 }
614 break;
615 case 'check':
616 if (!$fields['items']) {
617 $fields['type'] = 'boolean';
618 } else {
619 $fields['type'] = 'binary';
620 }
621 break;
622 case 'radio':
623 $fields['type'] = 'multiple';
624 break;
625 case 'select':
626 $fields['type'] = 'multiple';
627 if ($fields['foreign_table']) {
628 $fields['type'] = 'relation';
629 }
630 if ($fields['special']) {
631 $fields['type'] = 'text';
632 }
633 break;
634 case 'group':
635 $fields['type'] = 'files';
636 if ($fields['internal_type'] == 'db') {
637 $fields['type'] = 'relation';
638 }
639 break;
640 case 'user':
641 case 'flex':
642 case 'passthrough':
643 case 'none':
644 case 'text':
645 default:
646 $fields['type'] = 'text';
647 }
648 } else {
649 $fields['label'] = '[FIELD: ' . $fieldName . ']';
650 switch ($fieldName) {
651 case 'pid':
652 $fields['type'] = 'relation';
653 $fields['allowed'] = 'pages';
654 break;
655 case 'cruser_id':
656 $fields['type'] = 'relation';
657 $fields['allowed'] = 'be_users';
658 break;
659 case 'tstamp':
660
661 case 'crdate':
662 $fields['type'] = 'time';
663 break;
664 default:
665 $fields['type'] = 'number';
666 }
667 }
668 }
669 switch ($fields['type']) {
670 case 'date':
671 if ($fieldValue != -1) {
672 $out = strftime('%e-%m-%Y', $fieldValue);
673 }
674 break;
675 case 'time':
676 if ($fieldValue != -1) {
677 if ($splitString == '<br />') {
678 $out = strftime('%H:%M' . $splitString . '%e-%m-%Y', $fieldValue);
679 } else {
680 $out = strftime('%H:%M %e-%m-%Y', $fieldValue);
681 }
682 }
683 break;
684 case 'multiple':
685 case 'binary':
686 case 'relation':
687 $out = $this->makeValueList($fieldName, $fieldValue, $fields, $table, $splitString);
688 break;
689 case 'boolean':
690 $out = $fieldValue ? 'True' : 'False';
691 break;
692 case 'files':
693 default:
694 $out = htmlspecialchars($fieldValue);
695 }
696 return $out;
697 }
698
699 /**
700 * Get tree list
701 *
702 * @param int $id
703 * @param int $depth
704 * @param int $begin
705 * @param string $perms_clause
706 * @return string
707 */
708 public function getTreeList($id, $depth, $begin = 0, $perms_clause) {
709 $depth = (int)$depth;
710 $begin = (int)$begin;
711 $id = (int)$id;
712 if ($id < 0) {
713 $id = abs($id);
714 }
715 if ($begin == 0) {
716 $theList = $id;
717 } else {
718 $theList = '';
719 }
720 if ($id && $depth > 0) {
721 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid=' . $id . ' ' . BackendUtility::deleteClause('pages') . ' AND ' . $perms_clause);
722 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
723 if ($begin <= 0) {
724 $theList .= ',' . $row['uid'];
725 }
726 if ($depth > 1) {
727 $theList .= $this->getTreeList($row['uid'], $depth - 1, $begin - 1, $perms_clause);
728 }
729 }
730 $GLOBALS['TYPO3_DB']->sql_free_result($res);
731 }
732 return $theList;
733 }
734
735 /**
736 * Make value list
737 *
738 * @param string $fieldName
739 * @param string $fieldValue
740 * @param array $conf
741 * @param string $table
742 * @param string $splitString
743 * @return string
744 */
745 public function makeValueList($fieldName, $fieldValue, $conf, $table, $splitString) {
746 $fieldSetup = $conf;
747 $out = '';
748 if ($fieldSetup['type'] == 'files') {
749 $d = dir(PATH_site . $fieldSetup['uploadfolder']);
750 while (FALSE !== ($entry = $d->read())) {
751 if ($entry == '.' || $entry == '..') {
752 continue;
753 }
754 $fileArray[] = $entry;
755 }
756 $d->close();
757 natcasesort($fileArray);
758 while (list(, $fileName) = each($fileArray)) {
759 if (GeneralUtility::inList($fieldValue, $fileName) || $fieldValue == $fileName) {
760 if (!$out) {
761 $out = htmlspecialchars($fileName);
762 } else {
763 $out .= $splitString . htmlspecialchars($fileName);
764 }
765 }
766 }
767 }
768 if ($fieldSetup['type'] == 'multiple') {
769 foreach ($fieldSetup['items'] as $key => $val) {
770 if (substr($val[0], 0, 4) == 'LLL:') {
771 $value = $GLOBALS['LANG']->sL($val[0]);
772 } else {
773 $value = $val[0];
774 }
775 if (GeneralUtility::inList($fieldValue, $val[1]) || $fieldValue == $val[1]) {
776 if (!$out) {
777 $out = htmlspecialchars($value);
778 } else {
779 $out .= $splitString . htmlspecialchars($value);
780 }
781 }
782 }
783 }
784 if ($fieldSetup['type'] == 'binary') {
785 foreach ($fieldSetup['items'] as $Key => $val) {
786 if (substr($val[0], 0, 4) == 'LLL:') {
787 $value = $GLOBALS['LANG']->sL($val[0]);
788 } else {
789 $value = $val[0];
790 }
791 if (!$out) {
792 $out = htmlspecialchars($value);
793 } else {
794 $out .= $splitString . htmlspecialchars($value);
795 }
796 }
797 }
798 if ($fieldSetup['type'] == 'relation') {
799 if ($fieldSetup['items']) {
800 foreach ($fieldSetup['items'] as $key => $val) {
801 if (substr($val[0], 0, 4) == 'LLL:') {
802 $value = $GLOBALS['LANG']->sL($val[0]);
803 } else {
804 $value = $val[0];
805 }
806 if (GeneralUtility::inList($fieldValue, $value) || $fieldValue == $value) {
807 if (!$out) {
808 $out = htmlspecialchars($value);
809 } else {
810 $out .= $splitString . htmlspecialchars($value);
811 }
812 }
813 }
814 }
815 if (stristr($fieldSetup['allowed'], ',')) {
816 $from_table_Arr = explode(',', $fieldSetup['allowed']);
817 $useTablePrefix = 1;
818 if (!$fieldSetup['prepend_tname']) {
819 $checkres = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fieldName, $table, 'uid ' . BackendUtility::deleteClause($table), ($groupBy = ''), ($orderBy = ''), ($limit = ''));
820 if ($checkres) {
821 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($checkres)) {
822 if (stristr($row[$fieldName], ',')) {
823 $checkContent = explode(',', $row[$fieldName]);
824 foreach ($checkContent as $singleValue) {
825 if (!stristr($singleValue, '_')) {
826 $dontPrefixFirstTable = 1;
827 }
828 }
829 } else {
830 $singleValue = $row[$fieldName];
831 if (strlen($singleValue) && !stristr($singleValue, '_')) {
832 $dontPrefixFirstTable = 1;
833 }
834 }
835 }
836 $GLOBALS['TYPO3_DB']->sql_free_result($checkres);
837 }
838 }
839 } else {
840 $from_table_Arr[0] = $fieldSetup['allowed'];
841 }
842 if ($fieldSetup['prepend_tname']) {
843 $useTablePrefix = 1;
844 }
845 if ($fieldSetup['foreign_table']) {
846 $from_table_Arr[0] = $fieldSetup['foreign_table'];
847 }
848 $counter = 0;
849 foreach ($from_table_Arr as $from_table) {
850 if ($useTablePrefix && !$dontPrefixFirstTable && $counter != 1 || $counter == 1) {
851 $tablePrefix = $from_table . '_';
852 }
853 $counter = 1;
854 if (is_array($GLOBALS['TCA'][$from_table])) {
855 $labelField = $GLOBALS['TCA'][$from_table]['ctrl']['label'];
856 $altLabelField = $GLOBALS['TCA'][$from_table]['ctrl']['label_alt'];
857 if ($GLOBALS['TCA'][$from_table]['columns'][$labelField]['config']['items']) {
858 foreach ($GLOBALS['TCA'][$from_table]['columns'][$labelField]['config']['items'] as $labelArray) {
859 if (substr($labelArray[0], 0, 4) == 'LLL:') {
860 $labelFieldSelect[$labelArray[1]] = $GLOBALS['LANG']->sL($labelArray[0]);
861 } else {
862 $labelFieldSelect[$labelArray[1]] = $labelArray[0];
863 }
864 }
865 $useSelectLabels = 1;
866 }
867 if ($GLOBALS['TCA'][$from_table]['columns'][$altLabelField]['config']['items']) {
868 foreach ($GLOBALS['TCA'][$from_table]['columns'][$altLabelField]['config']['items'] as $altLabelArray) {
869 if (substr($altLabelArray[0], 0, 4) == 'LLL:') {
870 $altLabelFieldSelect[$altLabelArray[1]] = $GLOBALS['LANG']->sL($altLabelArray[0]);
871 } else {
872 $altLabelFieldSelect[$altLabelArray[1]] = $altLabelArray[0];
873 }
874 }
875 $useAltSelectLabels = 1;
876 }
877 $altLabelFieldSelect = $altLabelField ? ',' . $altLabelField : '';
878 $select_fields = 'uid,' . $labelField . $altLabelFieldSelect;
879 if (!$GLOBALS['BE_USER']->isAdmin() && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts']) {
880 $webMounts = $GLOBALS['BE_USER']->returnWebmounts();
881 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
882 $webMountPageTree = '';
883 foreach ($webMounts as $key => $val) {
884 if ($webMountPageTree) {
885 $webMountPageTreePrefix = ',';
886 }
887 $webMountPageTree .= $webMountPageTreePrefix . $this->getTreeList($val, 999, ($begin = 0), $perms_clause);
888 }
889 if ($from_table == 'pages') {
890 $where_clause = 'uid IN (' . $webMountPageTree . ') ' . BackendUtility::deleteClause($from_table) . ' AND ' . $perms_clause;
891 } else {
892 $where_clause = 'pid IN (' . $webMountPageTree . ') ' . BackendUtility::deleteClause($from_table);
893 }
894 } else {
895 $where_clause = 'uid' . BackendUtility::deleteClause($from_table);
896 }
897 $orderBy = 'uid';
898 if (!$this->tableArray[$from_table]) {
899 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select_fields, $from_table, $where_clause, ($groupBy = ''), $orderBy, ($limit = ''));
900 $this->tableArray[$from_table] = array();
901 }
902 if ($res) {
903 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
904 $this->tableArray[$from_table][] = $row;
905 }
906 $GLOBALS['TYPO3_DB']->sql_free_result($res);
907 }
908 foreach ($this->tableArray[$from_table] as $key => $val) {
909 $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] = $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] == 1 ? 'on' : $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'];
910 $prefixString = $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] == 'on' ? '' : ' [' . $tablePrefix . $val['uid'] . '] ';
911 if (GeneralUtility::inList($fieldValue, $tablePrefix . $val['uid']) || $fieldValue == $tablePrefix . $val['uid']) {
912 if ($useSelectLabels) {
913 if (!$out) {
914 $out = htmlspecialchars($prefixString . $labelFieldSelect[$val[$labelField]]);
915 } else {
916 $out .= $splitString . htmlspecialchars(($prefixString . $labelFieldSelect[$val[$labelField]]));
917 }
918 } elseif ($val[$labelField]) {
919 if (!$out) {
920 $out = htmlspecialchars($prefixString . $val[$labelField]);
921 } else {
922 $out .= $splitString . htmlspecialchars(($prefixString . $val[$labelField]));
923 }
924 } elseif ($useAltSelectLabels) {
925 if (!$out) {
926 $out = htmlspecialchars($prefixString . $altLabelFieldSelect[$val[$altLabelField]]);
927 } else {
928 $out .= $splitString . htmlspecialchars(($prefixString . $altLabelFieldSelect[$val[$altLabelField]]));
929 }
930 } else {
931 if (!$out) {
932 $out = htmlspecialchars($prefixString . $val[$altLabelField]);
933 } else {
934 $out .= $splitString . htmlspecialchars(($prefixString . $val[$altLabelField]));
935 }
936 }
937 }
938 }
939 }
940 }
941 }
942 return $out;
943 }
944
945 /**
946 * Render table header
947 *
948 * @param array $row Table columns
949 * @param array $conf Table TCA
950 * @param string $table Table name
951 * @return string HTML of table header
952 */
953 public function resultRowTitles($row, $conf, $table) {
954 $SET = $GLOBALS['SOBE']->MOD_SETTINGS;
955 $tableHeader = array();
956 // Start header row
957 $tableHeader[] = '<thead><tr class="bgColor5">';
958 // Iterate over given columns
959 foreach ($row as $fieldName => $fieldValue) {
960 if (GeneralUtility::inList($SET['queryFields'], $fieldName) || !$SET['queryFields'] && $fieldName != 'pid' && $fieldName != 'deleted') {
961 $THparams = strlen($fieldValue) < 50 ? ' style="white-space:nowrap;"' : '';
962 if ($GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels']) {
963 $title = $GLOBALS['LANG']->sL($conf['columns'][$fieldName]['label'] ? $conf['columns'][$fieldName]['label'] : $fieldName, TRUE);
964 } else {
965 $title = $GLOBALS['LANG']->sL($fieldName, TRUE);
966 }
967 $tableHeader[] = '<th' . $THparams . '>' . $title . '</th>';
968 }
969 }
970 // Add empty icon column
971 $tableHeader[] = '<th style="white-space:nowrap;"></th>';
972 // Close header row
973 $tableHeader[] = '</tr></thead>';
974 return implode(LF, $tableHeader);
975 }
976
977 /**
978 * CSV row titles
979 *
980 * @param array $row
981 * @param array $conf
982 * @param mixed $table Not used
983 * @return string
984 */
985 public function csvRowTitles($row, $conf, $table) {
986 $out = '';
987 $SET = $GLOBALS['SOBE']->MOD_SETTINGS;
988 foreach ($row as $fieldName => $fieldValue) {
989 if (GeneralUtility::inList($SET['queryFields'], $fieldName) || !$SET['queryFields'] && $fieldName != 'pid') {
990 if (!$out) {
991 if ($GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels']) {
992 $out = $GLOBALS['LANG']->sL($conf['columns'][$fieldName]['label'] ? $conf['columns'][$fieldName]['label'] : $fieldName, TRUE);
993 } else {
994 $out = $GLOBALS['LANG']->sL($fieldName, TRUE);
995 }
996 } else {
997 if ($GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels']) {
998 $out .= ',' . $GLOBALS['LANG']->sL(($conf['columns'][$fieldName]['label'] ? $conf['columns'][$fieldName]['label'] : $fieldName), TRUE);
999 } else {
1000 $out .= ',' . $GLOBALS['LANG']->sL($fieldName, TRUE);
1001 }
1002 }
1003 }
1004 }
1005 return $out;
1006 }
1007
1008 /**
1009 * Sets the current name of the input form.
1010 *
1011 * @param string $formName The name of the form.
1012 * @return void
1013 */
1014 public function setFormName($formName) {
1015 $this->formName = trim($formName);
1016 }
1017
1018 }