[TASK] Replace sprite icon "actions-edit-restore" with the new IconFactory
[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\Imaging\Icon;
18 use TYPO3\CMS\Core\Imaging\IconFactory;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
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 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_t3lib_fullsearch.xlf');
68 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
69 }
70
71 /**
72 * Get form
73 *
74 * @return string
75 */
76 public function form() {
77 return '
78 <div class="form-group">
79 <input placeholder="Search Word" class="form-control" type="search" name="SET[sword]" value="' . htmlspecialchars($GLOBALS['SOBE']->MOD_SETTINGS['sword']) . '">
80 </div>
81 <div class="form-group">
82 <input class="btn btn-default" type="submit" name="submit" value="Search All Records">
83 </div>
84 ';
85 }
86
87 /**
88 * Make store control
89 *
90 * @return string
91 */
92 public function makeStoreControl() {
93 // Load/Save
94 $storeArray = $this->initStoreArray();
95
96 $opt = array();
97 foreach ($storeArray as $k => $v) {
98 $opt[] = '<option value="' . $k . '">' . htmlspecialchars($v) . '</option>';
99 }
100 // Actions:
101 if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('sys_action') && $GLOBALS['BE_USER']->isAdmin()) {
102 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_action', 'type=2', '', 'title');
103 $opt[] = '<option value="0">__Save to Action:__</option>';
104 foreach($rows as $row) {
105 $opt[] = '<option value="-' . $row['uid'] . '">' . htmlspecialchars(($row['title'] . ' [' . $row['uid'] . ']')) . '</option>';
106 }
107 }
108 return '<div class="load-queries">
109 <div class="form-inline">
110 <div class="form-group">
111 <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>
112 <input class="btn btn-default" type="submit" name="storeControl[LOAD]" value="Load">
113 </div>
114 </div>
115 <div class="form-inline">
116 <div class="form-group">
117 <input name="storeControl[title]" value="" type="text" max="80" class="form-control">
118 <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?\');">
119 <input class="btn btn-default" type="submit" name="storeControl[REMOVE]" value="Remove">
120 </div>
121 </div>
122 </div>';
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 .= '<div id="query"></div>' . $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 '<div class="query-builder">' . $output . '</div>';
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 (!empty($rowArr)) {
400 $out .= '<table class="table table-striped table-hover">' . $this->resultRowTitles($lrow, $GLOBALS['TCA'][$table], $table) . implode(LF, $rowArr) . '</table>';
401 }
402 if (!$out) {
403 $out = '<div class="alert-info">No rows selected!</div>';
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 (!empty($rowArr)) {
419 $out .= '<textarea name="whatever" rows="20" wrap="off"' . $GLOBALS['SOBE']->doc->formWidth($this->formW) . ' class="text-monospace">' . htmlspecialchars(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 '<pre>' . $str . '</pre>';
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 if ($swords) {
492 foreach ($GLOBALS['TCA'] as $table => $value) {
493 // Get fields list
494 $conf = $GLOBALS['TCA'][$table];
495 // Avoid querying tables with no columns
496 if (empty($conf['columns'])) {
497 continue;
498 }
499 $fieldsInDatabase = $GLOBALS['TYPO3_DB']->admin_get_fields($table);
500 $list = array_intersect(array_keys($conf['columns']), array_keys($fieldsInDatabase));
501 // Get query
502 $qp = $GLOBALS['TYPO3_DB']->searchQuery(array($swords), $list, $table);
503 // Count:
504 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', $table, $qp . BackendUtility::deleteClause($table));
505 if ($count) {
506 $rowArr = array();
507 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,' . $conf['ctrl']['label'], $table, $qp . BackendUtility::deleteClause($table), '', '', $limit);
508 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
509 $rowArr[] = $this->resultRowDisplay($row, $conf, $table);
510 $lrow = $row;
511 }
512 $GLOBALS['TYPO3_DB']->sql_free_result($res);
513 $out .= '<div class="panel panel-default">
514 <div class="panel-heading">' . $GLOBALS['LANG']->sL($conf['ctrl']['title'], TRUE) . ' (' . $count . ')</div>
515 <table class="table table-striped table-hover">' .
516 $this->resultRowTitles($lrow, $conf, $table) .
517 implode(LF, $rowArr) .
518 '</table>
519 </div>';
520 }
521 }
522 }
523 return $out;
524 }
525
526 /**
527 * Result row display
528 *
529 * @param array $row
530 * @param array $conf
531 * @param string $table
532 * @return string
533 */
534 public function resultRowDisplay($row, $conf, $table) {
535 /** @var IconFactory $iconFactory */
536 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
537 $SET = $GLOBALS['SOBE']->MOD_SETTINGS;
538 $out = '<tr>';
539 foreach ($row as $fieldName => $fieldValue) {
540 if (GeneralUtility::inList($SET['queryFields'], $fieldName) || !$SET['queryFields'] && $fieldName != 'pid' && $fieldName != 'deleted') {
541 if ($SET['search_result_labels']) {
542 $fVnew = $this->getProcessedValueExtra($table, $fieldName, $fieldValue, $conf, '<br />');
543 } else {
544 $fVnew = htmlspecialchars($fieldValue);
545 }
546 $out .= '<td>' . $fVnew . '</td>';
547 }
548 }
549 $params = '&edit[' . $table . '][' . $row['uid'] . ']=edit';
550 $out .= '<td><div class="btn-group">';
551 if (!$row['deleted']) {
552 $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>';
553 $out .= '<a class="btn btn-default" href="#" onClick="' . htmlspecialchars(BackendUtility::editOnClick($params, '', GeneralUtility::getIndpEnv('REQUEST_URI') . GeneralUtility::implodeArrayForUrl('SET', (array)GeneralUtility::_POST('SET')))) . '">' . $iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL) . '</a>';
554 } else {
555 $out .= '<a class="btn btn-default" href="' . GeneralUtility::linkThisUrl(BackendUtility::getModuleUrl('tce_db'), array(
556 ('cmd[' . $table . '][' . $row['uid'] . '][undelete]') => '1',
557 'redirect' => GeneralUtility::linkThisScript(array())
558 )) . BackendUtility::getUrlToken('tceAction') . '" title="' . $GLOBALS['LANG']-getLL('undelete_only', TRUE) . '">';
559 $out .= $this->iconFactory->getIcon('actions-edit-restore', Icon::SIZE_SMALL) . '</a>';
560 $formEngineParameters = array(
561 'edit[' . $table . '][' . $row['uid'] . ']' => 'edit',
562 'returnUrl' => GeneralUtility::linkThisScript(array())
563 );
564 $redirectUrl = BackendUtility::getModuleUrl('record_edit', $formEngineParameters);
565 $out .= '<a class="btn btn-default" href="' . GeneralUtility::linkThisUrl(BackendUtility::getModuleUrl('tce_db'), array(
566 ('cmd[' . $table . '][' . $row['uid'] . '][undelete]') => '1',
567 'redirect' => $redirectUrl
568 )) . BackendUtility::getUrlToken('tceAction') . '">';
569 $out .= \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-restore-edit', array('title' => 'undelete and edit')) . '</a>';
570 }
571 $_params = array($table => $row);
572 if (is_array($this->hookArray['additionalButtons'])) {
573 foreach ($this->hookArray['additionalButtons'] as $_funcRef) {
574 $out .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
575 }
576 }
577 $out .= '</div></td>
578 </tr>
579 ';
580 return $out;
581 }
582
583 /**
584 * Get processed value extra
585 *
586 * @param string $table
587 * @param string $fieldName
588 * @param string $fieldValue
589 * @param array $conf Not used
590 * @param string $splitString
591 * @return string
592 */
593 public function getProcessedValueExtra($table, $fieldName, $fieldValue, $conf, $splitString) {
594 $out = '';
595 // Analysing the fields in the table.
596 if (is_array($GLOBALS['TCA'][$table])) {
597 $fC = $GLOBALS['TCA'][$table]['columns'][$fieldName];
598 $fields = $fC['config'];
599 $fields['exclude'] = $fC['exclude'];
600 if (is_array($fC) && $fC['label']) {
601 $fields['label'] = preg_replace('/:$/', '', trim($GLOBALS['LANG']->sL($fC['label'])));
602 switch ($fields['type']) {
603 case 'input':
604 if (preg_match('/int|year/i', $fields['eval'])) {
605 $fields['type'] = 'number';
606 } elseif (preg_match('/time/i', $fields['eval'])) {
607 $fields['type'] = 'time';
608 } elseif (preg_match('/date/i', $fields['eval'])) {
609 $fields['type'] = 'date';
610 } else {
611 $fields['type'] = 'text';
612 }
613 break;
614 case 'check':
615 if (!$fields['items']) {
616 $fields['type'] = 'boolean';
617 } else {
618 $fields['type'] = 'binary';
619 }
620 break;
621 case 'radio':
622 $fields['type'] = 'multiple';
623 break;
624 case 'select':
625 $fields['type'] = 'multiple';
626 if ($fields['foreign_table']) {
627 $fields['type'] = 'relation';
628 }
629 if ($fields['special']) {
630 $fields['type'] = 'text';
631 }
632 break;
633 case 'group':
634 $fields['type'] = 'files';
635 if ($fields['internal_type'] == 'db') {
636 $fields['type'] = 'relation';
637 }
638 break;
639 case 'user':
640 case 'flex':
641 case 'passthrough':
642 case 'none':
643 case 'text':
644 default:
645 $fields['type'] = 'text';
646 }
647 } else {
648 $fields['label'] = '[FIELD: ' . $fieldName . ']';
649 switch ($fieldName) {
650 case 'pid':
651 $fields['type'] = 'relation';
652 $fields['allowed'] = 'pages';
653 break;
654 case 'cruser_id':
655 $fields['type'] = 'relation';
656 $fields['allowed'] = 'be_users';
657 break;
658 case 'tstamp':
659
660 case 'crdate':
661 $fields['type'] = 'time';
662 break;
663 default:
664 $fields['type'] = 'number';
665 }
666 }
667 }
668 switch ($fields['type']) {
669 case 'date':
670 if ($fieldValue != -1) {
671 $out = strftime('%e-%m-%Y', $fieldValue);
672 }
673 break;
674 case 'time':
675 if ($fieldValue != -1) {
676 if ($splitString == '<br />') {
677 $out = strftime('%H:%M' . $splitString . '%e-%m-%Y', $fieldValue);
678 } else {
679 $out = strftime('%H:%M %e-%m-%Y', $fieldValue);
680 }
681 }
682 break;
683 case 'multiple':
684 case 'binary':
685 case 'relation':
686 $out = $this->makeValueList($fieldName, $fieldValue, $fields, $table, $splitString);
687 break;
688 case 'boolean':
689 $out = $fieldValue ? 'True' : 'False';
690 break;
691 case 'files':
692 default:
693 $out = htmlspecialchars($fieldValue);
694 }
695 return $out;
696 }
697
698 /**
699 * Get tree list
700 *
701 * @param int $id
702 * @param int $depth
703 * @param int $begin
704 * @param string $perms_clause
705 * @return string
706 */
707 public function getTreeList($id, $depth, $begin = 0, $perms_clause) {
708 $depth = (int)$depth;
709 $begin = (int)$begin;
710 $id = (int)$id;
711 if ($id < 0) {
712 $id = abs($id);
713 }
714 if ($begin == 0) {
715 $theList = $id;
716 } else {
717 $theList = '';
718 }
719 if ($id && $depth > 0) {
720 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid=' . $id . ' ' . BackendUtility::deleteClause('pages') . ' AND ' . $perms_clause);
721 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
722 if ($begin <= 0) {
723 $theList .= ',' . $row['uid'];
724 }
725 if ($depth > 1) {
726 $theList .= $this->getTreeList($row['uid'], $depth - 1, $begin - 1, $perms_clause);
727 }
728 }
729 $GLOBALS['TYPO3_DB']->sql_free_result($res);
730 }
731 return $theList;
732 }
733
734 /**
735 * Make value list
736 *
737 * @param string $fieldName
738 * @param string $fieldValue
739 * @param array $conf
740 * @param string $table
741 * @param string $splitString
742 * @return string
743 */
744 public function makeValueList($fieldName, $fieldValue, $conf, $table, $splitString) {
745 $fieldSetup = $conf;
746 $out = '';
747 if ($fieldSetup['type'] == 'files') {
748 $d = dir(PATH_site . $fieldSetup['uploadfolder']);
749 while (FALSE !== ($entry = $d->read())) {
750 if ($entry == '.' || $entry == '..') {
751 continue;
752 }
753 $fileArray[] = $entry;
754 }
755 $d->close();
756 natcasesort($fileArray);
757 foreach ($fileArray as $fileName) {
758 if (GeneralUtility::inList($fieldValue, $fileName) || $fieldValue == $fileName) {
759 if (!$out) {
760 $out = htmlspecialchars($fileName);
761 } else {
762 $out .= $splitString . htmlspecialchars($fileName);
763 }
764 }
765 }
766 }
767 if ($fieldSetup['type'] == 'multiple') {
768 foreach ($fieldSetup['items'] as $key => $val) {
769 if (substr($val[0], 0, 4) == 'LLL:') {
770 $value = $GLOBALS['LANG']->sL($val[0]);
771 } else {
772 $value = $val[0];
773 }
774 if (GeneralUtility::inList($fieldValue, $val[1]) || $fieldValue == $val[1]) {
775 if (!$out) {
776 $out = htmlspecialchars($value);
777 } else {
778 $out .= $splitString . htmlspecialchars($value);
779 }
780 }
781 }
782 }
783 if ($fieldSetup['type'] == 'binary') {
784 foreach ($fieldSetup['items'] as $Key => $val) {
785 if (substr($val[0], 0, 4) == 'LLL:') {
786 $value = $GLOBALS['LANG']->sL($val[0]);
787 } else {
788 $value = $val[0];
789 }
790 if (!$out) {
791 $out = htmlspecialchars($value);
792 } else {
793 $out .= $splitString . htmlspecialchars($value);
794 }
795 }
796 }
797 if ($fieldSetup['type'] == 'relation') {
798 if ($fieldSetup['items']) {
799 foreach ($fieldSetup['items'] as $key => $val) {
800 if (substr($val[0], 0, 4) == 'LLL:') {
801 $value = $GLOBALS['LANG']->sL($val[0]);
802 } else {
803 $value = $val[0];
804 }
805 if (GeneralUtility::inList($fieldValue, $value) || $fieldValue == $value) {
806 if (!$out) {
807 $out = htmlspecialchars($value);
808 } else {
809 $out .= $splitString . htmlspecialchars($value);
810 }
811 }
812 }
813 }
814 if (stristr($fieldSetup['allowed'], ',')) {
815 $from_table_Arr = explode(',', $fieldSetup['allowed']);
816 $useTablePrefix = 1;
817 if (!$fieldSetup['prepend_tname']) {
818 $checkres = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fieldName, $table, 'uid ' . BackendUtility::deleteClause($table), ($groupBy = ''), ($orderBy = ''), ($limit = ''));
819 if ($checkres) {
820 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($checkres)) {
821 if (stristr($row[$fieldName], ',')) {
822 $checkContent = explode(',', $row[$fieldName]);
823 foreach ($checkContent as $singleValue) {
824 if (!stristr($singleValue, '_')) {
825 $dontPrefixFirstTable = 1;
826 }
827 }
828 } else {
829 $singleValue = $row[$fieldName];
830 if ($singleValue !== '' && !stristr($singleValue, '_')) {
831 $dontPrefixFirstTable = 1;
832 }
833 }
834 }
835 $GLOBALS['TYPO3_DB']->sql_free_result($checkres);
836 }
837 }
838 } else {
839 $from_table_Arr[0] = $fieldSetup['allowed'];
840 }
841 if ($fieldSetup['prepend_tname']) {
842 $useTablePrefix = 1;
843 }
844 if ($fieldSetup['foreign_table']) {
845 $from_table_Arr[0] = $fieldSetup['foreign_table'];
846 }
847 $counter = 0;
848 foreach ($from_table_Arr as $from_table) {
849 if ($useTablePrefix && !$dontPrefixFirstTable && $counter != 1 || $counter == 1) {
850 $tablePrefix = $from_table . '_';
851 }
852 $counter = 1;
853 if (is_array($GLOBALS['TCA'][$from_table])) {
854 $labelField = $GLOBALS['TCA'][$from_table]['ctrl']['label'];
855 $altLabelField = $GLOBALS['TCA'][$from_table]['ctrl']['label_alt'];
856 if ($GLOBALS['TCA'][$from_table]['columns'][$labelField]['config']['items']) {
857 foreach ($GLOBALS['TCA'][$from_table]['columns'][$labelField]['config']['items'] as $labelArray) {
858 if (substr($labelArray[0], 0, 4) == 'LLL:') {
859 $labelFieldSelect[$labelArray[1]] = $GLOBALS['LANG']->sL($labelArray[0]);
860 } else {
861 $labelFieldSelect[$labelArray[1]] = $labelArray[0];
862 }
863 }
864 $useSelectLabels = 1;
865 }
866 if ($GLOBALS['TCA'][$from_table]['columns'][$altLabelField]['config']['items']) {
867 foreach ($GLOBALS['TCA'][$from_table]['columns'][$altLabelField]['config']['items'] as $altLabelArray) {
868 if (substr($altLabelArray[0], 0, 4) == 'LLL:') {
869 $altLabelFieldSelect[$altLabelArray[1]] = $GLOBALS['LANG']->sL($altLabelArray[0]);
870 } else {
871 $altLabelFieldSelect[$altLabelArray[1]] = $altLabelArray[0];
872 }
873 }
874 $useAltSelectLabels = 1;
875 }
876 $altLabelFieldSelect = $altLabelField ? ',' . $altLabelField : '';
877 $select_fields = 'uid,' . $labelField . $altLabelFieldSelect;
878 if (!$GLOBALS['BE_USER']->isAdmin() && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts']) {
879 $webMounts = $GLOBALS['BE_USER']->returnWebmounts();
880 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
881 $webMountPageTree = '';
882 foreach ($webMounts as $key => $val) {
883 if ($webMountPageTree) {
884 $webMountPageTreePrefix = ',';
885 }
886 $webMountPageTree .= $webMountPageTreePrefix . $this->getTreeList($val, 999, ($begin = 0), $perms_clause);
887 }
888 if ($from_table == 'pages') {
889 $where_clause = 'uid IN (' . $webMountPageTree . ') ' . BackendUtility::deleteClause($from_table) . ' AND ' . $perms_clause;
890 } else {
891 $where_clause = 'pid IN (' . $webMountPageTree . ') ' . BackendUtility::deleteClause($from_table);
892 }
893 } else {
894 $where_clause = 'uid' . BackendUtility::deleteClause($from_table);
895 }
896 $orderBy = 'uid';
897 if (!$this->tableArray[$from_table]) {
898 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select_fields, $from_table, $where_clause, ($groupBy = ''), $orderBy, ($limit = ''));
899 $this->tableArray[$from_table] = array();
900 }
901 if ($res) {
902 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
903 $this->tableArray[$from_table][] = $row;
904 }
905 $GLOBALS['TYPO3_DB']->sql_free_result($res);
906 }
907 foreach ($this->tableArray[$from_table] as $key => $val) {
908 $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] = $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] == 1 ? 'on' : $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'];
909 $prefixString = $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] == 'on' ? '' : ' [' . $tablePrefix . $val['uid'] . '] ';
910 if (GeneralUtility::inList($fieldValue, $tablePrefix . $val['uid']) || $fieldValue == $tablePrefix . $val['uid']) {
911 if ($useSelectLabels) {
912 if (!$out) {
913 $out = htmlspecialchars($prefixString . $labelFieldSelect[$val[$labelField]]);
914 } else {
915 $out .= $splitString . htmlspecialchars(($prefixString . $labelFieldSelect[$val[$labelField]]));
916 }
917 } elseif ($val[$labelField]) {
918 if (!$out) {
919 $out = htmlspecialchars($prefixString . $val[$labelField]);
920 } else {
921 $out .= $splitString . htmlspecialchars(($prefixString . $val[$labelField]));
922 }
923 } elseif ($useAltSelectLabels) {
924 if (!$out) {
925 $out = htmlspecialchars($prefixString . $altLabelFieldSelect[$val[$altLabelField]]);
926 } else {
927 $out .= $splitString . htmlspecialchars(($prefixString . $altLabelFieldSelect[$val[$altLabelField]]));
928 }
929 } else {
930 if (!$out) {
931 $out = htmlspecialchars($prefixString . $val[$altLabelField]);
932 } else {
933 $out .= $splitString . htmlspecialchars(($prefixString . $val[$altLabelField]));
934 }
935 }
936 }
937 }
938 }
939 }
940 }
941 return $out;
942 }
943
944 /**
945 * Render table header
946 *
947 * @param array $row Table columns
948 * @param array $conf Table TCA
949 * @param string $table Table name
950 * @return string HTML of table header
951 */
952 public function resultRowTitles($row, $conf, $table) {
953 $SET = $GLOBALS['SOBE']->MOD_SETTINGS;
954 $tableHeader = array();
955 // Start header row
956 $tableHeader[] = '<thead><tr>';
957 // Iterate over given columns
958 foreach ($row as $fieldName => $fieldValue) {
959 if (GeneralUtility::inList($SET['queryFields'], $fieldName) || !$SET['queryFields'] && $fieldName != 'pid' && $fieldName != 'deleted') {
960 if ($GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels']) {
961 $title = $GLOBALS['LANG']->sL($conf['columns'][$fieldName]['label'] ? $conf['columns'][$fieldName]['label'] : $fieldName, TRUE);
962 } else {
963 $title = $GLOBALS['LANG']->sL($fieldName, TRUE);
964 }
965 $tableHeader[] = '<th>' . $title . '</th>';
966 }
967 }
968 // Add empty icon column
969 $tableHeader[] = '<th></th>';
970 // Close header row
971 $tableHeader[] = '</tr></thead>';
972 return implode(LF, $tableHeader);
973 }
974
975 /**
976 * CSV row titles
977 *
978 * @param array $row
979 * @param array $conf
980 * @param mixed $table Not used
981 * @return string
982 */
983 public function csvRowTitles($row, $conf, $table) {
984 $out = '';
985 $SET = $GLOBALS['SOBE']->MOD_SETTINGS;
986 foreach ($row as $fieldName => $fieldValue) {
987 if (GeneralUtility::inList($SET['queryFields'], $fieldName) || !$SET['queryFields'] && $fieldName != 'pid') {
988 if (!$out) {
989 if ($GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels']) {
990 $out = $GLOBALS['LANG']->sL($conf['columns'][$fieldName]['label'] ? $conf['columns'][$fieldName]['label'] : $fieldName, TRUE);
991 } else {
992 $out = $GLOBALS['LANG']->sL($fieldName, TRUE);
993 }
994 } else {
995 if ($GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels']) {
996 $out .= ',' . $GLOBALS['LANG']->sL(($conf['columns'][$fieldName]['label'] ? $conf['columns'][$fieldName]['label'] : $fieldName), TRUE);
997 } else {
998 $out .= ',' . $GLOBALS['LANG']->sL($fieldName, TRUE);
999 }
1000 }
1001 }
1002 }
1003 return $out;
1004 }
1005
1006 /**
1007 * Sets the current name of the input form.
1008 *
1009 * @param string $formName The name of the form.
1010 * @return void
1011 */
1012 public function setFormName($formName) {
1013 $this->formName = trim($formName);
1014 }
1015
1016 }