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