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