TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
SuggestWizardDefaultReceiver.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\Form\Wizard;
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 
29 
37 {
43  protected $table = '';
44 
51  protected $mmForeignTable = '';
52 
58  protected $config = [];
59 
65  protected $allowedPages = [];
66 
72  protected $maxItems = 10;
73 
77  protected $params = [];
78 
82  protected $iconFactory;
83 
87  protected $queryBuilder;
88 
95  public function __construct($table, $config)
96  {
97  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
98  $this->queryBuilder = $this->getQueryBuilderForTable($table);
99  $this->queryBuilder->getRestrictions()
100  ->removeAll()
101  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
102  // if table is versionized, only get the records from the Live Workspace
103  // the overlay itself of WS-records is done below
104  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, 0));
105  $this->table = $table;
106  $this->config = $config;
107  // get a list of all the pages that should be looked on
108  if (isset($config['pidList'])) {
109  $allowedPages = ($pageIds = GeneralUtility::trimExplode(',', $config['pidList']));
110  $depth = (int)$config['pidDepth'];
111  foreach ($pageIds as $pageId) {
112  if ($pageId > 0) {
114  }
115  }
116  $this->allowedPages = array_unique($allowedPages);
117  }
118  if (isset($config['maxItemsInResultList'])) {
119  $this->maxItems = $config['maxItemsInResultList'];
120  }
121  if ($this->table == 'pages') {
122  $this->queryBuilder->andWhere(
123  QueryHelper::stripLogicalOperatorPrefix($GLOBALS['BE_USER']->getPagePermsClause(1))
124  );
125  }
126  if (isset($config['addWhere'])) {
127  $this->queryBuilder->andWhere(
129  );
130  }
131  }
132 
145  public function queryTable(&$params, $recursionCounter = 0)
146  {
147  $rows = [];
148  $this->params = &$params;
149  $start = $recursionCounter * 50;
150  $this->prepareSelectStatement();
151  $this->prepareOrderByStatement();
152  $result = $this->queryBuilder->select('*')
153  ->from($this->table)
154  ->setFirstResult($start)
155  ->setMaxResults(50)
156  ->execute();
157  $allRowsCount = $result->rowCount();
158  if ($allRowsCount) {
160  $charsetConverter = GeneralUtility::makeInstance(CharsetConverter::class);
161  while ($row = $result->fetch()) {
162  // check if we already have collected the maximum number of records
163  if (count($rows) > $this->maxItems) {
164  break;
165  }
166  $this->manipulateRecord($row);
167  $this->makeWorkspaceOverlay($row);
168  // check if the user has access to the record
169  if (!$this->checkRecordAccess($row, $row['uid'])) {
170  continue;
171  }
172  $spriteIcon = $this->iconFactory->getIconForRecord($this->table, $row, Icon::SIZE_SMALL)->render();
173  $uid = $row['t3ver_oid'] > 0 ? $row['t3ver_oid'] : $row['uid'];
174  $path = $this->getRecordPath($row, $uid);
175  if (strlen($path) > 30) {
176  $croppedPath = '<abbr title="' . htmlspecialchars($path) . '">' .
177  htmlspecialchars(
178  $charsetConverter->crop('utf-8', $path, 10)
179  . '...'
180  . $charsetConverter->crop('utf-8', $path, -20)
181  ) .
182  '</abbr>';
183  } else {
184  $croppedPath = htmlspecialchars($path);
185  }
186  $label = $this->getLabel($row);
187  $entry = [
188  'text' => '<span class="suggest-label">' . $label . '</span><span class="suggest-uid">[' . $uid . ']</span><br />
189  <span class="suggest-path">' . $croppedPath . '</span>',
190  'table' => $this->mmForeignTable ? $this->mmForeignTable : $this->table,
191  'label' => $label,
192  'path' => $path,
193  'uid' => $uid,
194  'style' => '',
195  'class' => isset($this->config['cssClass']) ? $this->config['cssClass'] : '',
196  'sprite' => $spriteIcon
197  ];
198  $rows[$this->table . '_' . $uid] = $this->renderRecord($row, $entry);
199  }
200 
201  // if there are less records than we need, call this function again to get more records
202  if (count($rows) < $this->maxItems && $allRowsCount >= 50 && $recursionCounter < $this->maxItems) {
203  $tmp = self::queryTable($params, ++$recursionCounter);
204  $rows = array_merge($tmp, $rows);
205  }
206  }
207  return $rows;
208  }
209 
216  protected function prepareSelectStatement()
217  {
218  $expressionBuilder = $this->queryBuilder->expr();
219  $searchWholePhrase = !isset($this->config['searchWholePhrase']) || $this->config['searchWholePhrase'];
220  $searchString = $this->params['value'];
221  $searchUid = (int)$searchString;
222  if ($searchString !== '') {
223  $likeCondition = ($searchWholePhrase ? '%' : '') . $searchString . '%';
224  // Search in all fields given by label or label_alt
225  $selectFieldsList = $GLOBALS['TCA'][$this->table]['ctrl']['label'] . ',' . $GLOBALS['TCA'][$this->table]['ctrl']['label_alt'] . ',' . $this->config['additionalSearchFields'];
226  $selectFields = GeneralUtility::trimExplode(',', $selectFieldsList, true);
227  $selectFields = array_unique($selectFields);
228  $selectParts = $expressionBuilder->orX();
229  foreach ($selectFields as $field) {
230  $selectParts->add($expressionBuilder->like($field, $this->queryBuilder->createPositionalParameter($likeCondition)));
231  }
232 
233  $searchClause = $expressionBuilder->orX($selectParts);
234  if ($searchUid > 0 && $searchUid == $searchString) {
235  $searchClause->add($expressionBuilder->eq('uid', $searchUid));
236  }
237 
238  $this->queryBuilder->andWhere($expressionBuilder->orX($searchClause));
239  }
240  if (!empty($this->allowedPages)) {
241  $pidList = array_map('intval', $this->allowedPages);
242  if (!empty($pidList)) {
243  $this->queryBuilder->andWhere(
244  $expressionBuilder->in('pid', $pidList)
245  );
246  }
247  }
248  // add an additional search condition comment
249  if (isset($this->config['searchCondition']) && $this->config['searchCondition'] !== '') {
250  $this->queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($this->config['searchCondition']));
251  }
252  }
253 
261  protected function getAllSubpagesOfPage($uid, $depth = 99)
262  {
263  $pageIds = [$uid];
264  $level = 0;
265  $pages = [$uid];
266  $queryBuilder = $this->getQueryBuilderForTable('pages');
267  $queryBuilder->select('uid')
268  ->from('pages');
269  // fetch all
270  while ($depth - $level > 0 && !empty($pageIds)) {
271  ++$level;
272  $rows = $queryBuilder
273  ->where(
274  $queryBuilder->expr()->in(
275  'pid',
276  $queryBuilder->createNamedParameter($pageIds, Connection::PARAM_INT_ARRAY)
277  )
278  )
279  ->execute()
280  ->fetchAll();
281 
282  $rows = array_column(($rows ?: []), 'uid', 'uid');
283  if (!count($rows)) {
284  $pageIds = array_keys($rows);
285  $pages = array_merge($pages, $pageIds);
286  } else {
287  break;
288  }
289  }
290  return $pages;
291  }
292 
299  protected function prepareOrderByStatement()
300  {
301  if (empty($this->config['orderBy'])) {
302  $this->queryBuilder->addOrderBy($GLOBALS['TCA'][$this->table]['ctrl']['label']);
303  } else {
304  foreach (QueryHelper::parseOrderBy($this->config['orderBy']) as $orderPair) {
305  list($fieldName, $order) = $orderPair;
306  $this->queryBuilder->addOrderBy($fieldName, $order);
307  }
308  }
309  }
310 
316  protected function manipulateRecord(&$row)
317  {
318  }
319 
327  protected function checkRecordAccess($row, $uid)
328  {
329  $retValue = true;
330  $table = $this->mmForeignTable ?: $this->table;
331  if ($table == 'pages') {
332  if (!BackendUtility::readPageAccess($uid, $GLOBALS['BE_USER']->getPagePermsClause(1))) {
333  $retValue = false;
334  }
335  } elseif (isset($GLOBALS['TCA'][$table]['ctrl']['is_static']) && (bool)$GLOBALS['TCA'][$table]['ctrl']['is_static']) {
336  $retValue = true;
337  } else {
338  if (!is_array(BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1)))) {
339  $retValue = false;
340  }
341  }
342  return $retValue;
343  }
344 
351  protected function makeWorkspaceOverlay(&$row)
352  {
353  // Check for workspace-versions
354  if ($GLOBALS['BE_USER']->workspace != 0 && $GLOBALS['TCA'][$this->table]['ctrl']['versioningWS'] == true) {
355  BackendUtility::workspaceOL($this->mmForeignTable ? $this->mmForeignTable : $this->table, $row);
356  }
357  }
358 
369  protected function getRecordPath(&$row, $uid)
370  {
371  $titleLimit = max($this->config['maxPathTitleLength'], 0);
372  if (($this->mmForeignTable ? $this->mmForeignTable : $this->table) == 'pages') {
373  $path = BackendUtility::getRecordPath($uid, '', $titleLimit);
374  // For pages we only want the first (n-1) parts of the path,
375  // because the n-th part is the page itself
376  $path = substr($path, 0, strrpos($path, '/', -2)) . '/';
377  } else {
378  $path = BackendUtility::getRecordPath($row['pid'], '', $titleLimit);
379  }
380  return $path;
381  }
382 
389  protected function getLabel($row)
390  {
391  return BackendUtility::getRecordTitle($this->mmForeignTable ? $this->mmForeignTable : $this->table, $row, true);
392  }
393 
403  protected function renderRecord($row, $entry)
404  {
405  // Call renderlet if available (normal pages etc. usually don't have one)
406  if ($this->config['renderFunc'] != '') {
407  $params = [
408  'table' => $this->table,
409  'uid' => $row['uid'],
410  'row' => $row,
411  'entry' => &$entry
412  ];
413  GeneralUtility::callUserFunction($this->config['renderFunc'], $params, $this);
414  }
415  return $entry;
416  }
417 
421  protected function getLanguageService()
422  {
423  return $GLOBALS['LANG'];
424  }
425 
430  protected function getQueryBuilderForTable($table)
431  {
432  return GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
433  }
434 }
static getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
static stripLogicalOperatorPrefix(string $constraint)
static callUserFunction($funcName, &$params, &$ref, $_= '', $errorMode=0)