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