‪TYPO3CMS  9.5
Typo3DbBackend.php
Go to the documentation of this file.
1 <?php
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 Doctrine\DBAL\DBALException;
18 use Doctrine\DBAL\Platforms\SQLServerPlatform;
42 
48 {
52  protected ‪$connectionPool;
53 
57  protected ‪$configurationManager;
58 
62  protected ‪$cacheService;
63 
68 
72  protected ‪$objectManager;
73 
80  protected ‪$hasPidColumn = [];
81 
86  {
87  $this->configurationManager = ‪$configurationManager;
88  }
89 
94  {
95  $this->cacheService = ‪$cacheService;
96  }
97 
102  {
103  $this->environmentService = ‪$environmentService;
104  }
105 
110  {
111  $this->objectManager = ‪$objectManager;
112  }
113 
117  public function ‪__construct()
118  {
119  $this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
120  }
121 
131  public function ‪addRow($tableName, array $fieldValues, $isRelation = false)
132  {
133  if (isset($fieldValues['uid'])) {
134  unset($fieldValues['uid']);
135  }
136  try {
137  $connection = $this->connectionPool->getConnectionForTable($tableName);
138 
139  $types = [];
140  $platform = $connection->getDatabasePlatform();
141  if ($platform instanceof SQLServerPlatform) {
142  // mssql needs to set proper PARAM_LOB and others to update fields
143  $tableDetails = $connection->getSchemaManager()->listTableDetails($tableName);
144  foreach ($fieldValues as $columnName => $columnValue) {
145  $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
146  }
147  }
148 
149  $connection->insert($tableName, $fieldValues, $types);
150  } catch (DBALException $e) {
151  throw new SqlErrorException($e->getPrevious()->getMessage(), 1470230766, $e);
152  }
153 
154  $uid = 0;
155  if (!$isRelation) {
156  // Relation tables have no auto_increment column, so no retrieval must be tried.
157  $uid = $connection->lastInsertId($tableName);
158  $this->‪clearPageCache($tableName, $uid);
159  }
160  return (int)$uid;
161  }
162 
173  public function ‪updateRow($tableName, array $fieldValues, $isRelation = false)
174  {
175  if (!isset($fieldValues['uid'])) {
176  throw new \InvalidArgumentException('The given row must contain a value for "uid".', 1476045164);
177  }
178 
179  $uid = (int)$fieldValues['uid'];
180  unset($fieldValues['uid']);
181 
182  try {
183  $connection = $this->connectionPool->getConnectionForTable($tableName);
184 
185  $types = [];
186  $platform = $connection->getDatabasePlatform();
187  if ($platform instanceof SQLServerPlatform) {
188  // mssql needs to set proper PARAM_LOB and others to update fields
189  $tableDetails = $connection->getSchemaManager()->listTableDetails($tableName);
190  foreach ($fieldValues as $columnName => $columnValue) {
191  $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
192  }
193  }
194 
195  $connection->update($tableName, $fieldValues, ['uid' => $uid], $types);
196  } catch (DBALException $e) {
197  throw new SqlErrorException($e->getPrevious()->getMessage(), 1470230767, $e);
198  }
199 
200  if (!$isRelation) {
201  $this->‪clearPageCache($tableName, $uid);
202  }
203 
204  // always returns true
205  return true;
206  }
207 
217  public function ‪updateRelationTableRow($tableName, array $fieldValues)
218  {
219  if (!isset($fieldValues['uid_local']) && !isset($fieldValues['uid_foreign'])) {
220  throw new \InvalidArgumentException(
221  'The given fieldValues must contain a value for "uid_local" and "uid_foreign".',
222  1360500126
223  );
224  }
225 
226  $where['uid_local'] = (int)$fieldValues['uid_local'];
227  $where['uid_foreign'] = (int)$fieldValues['uid_foreign'];
228  unset($fieldValues['uid_local']);
229  unset($fieldValues['uid_foreign']);
230 
231  if (!empty($fieldValues['tablenames'])) {
232  $where['tablenames'] = $fieldValues['tablenames'];
233  unset($fieldValues['tablenames']);
234  }
235  if (!empty($fieldValues['fieldname'])) {
236  $where['fieldname'] = $fieldValues['fieldname'];
237  unset($fieldValues['fieldname']);
238  }
239 
240  try {
241  $this->connectionPool->getConnectionForTable($tableName)->update($tableName, $fieldValues, $where);
242  } catch (DBALException $e) {
243  throw new SqlErrorException($e->getPrevious()->getMessage(), 1470230768, $e);
244  }
245 
246  // always returns true
247  return true;
248  }
249 
259  public function ‪removeRow($tableName, array $where, $isRelation = false)
260  {
261  try {
262  $this->connectionPool->getConnectionForTable($tableName)->delete($tableName, $where);
263  } catch (DBALException $e) {
264  throw new SqlErrorException($e->getPrevious()->getMessage(), 1470230769, $e);
265  }
266 
267  if (!$isRelation && isset($where['uid'])) {
268  $this->‪clearPageCache($tableName, $where['uid']);
269  }
270 
271  // always returns true
272  return true;
273  }
274 
284  public function ‪getMaxValueFromTable($tableName, array $where, $columnName)
285  {
286  try {
287  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
288  $queryBuilder->getRestrictions()->removeAll();
289  $queryBuilder
290  ->select($columnName)
291  ->from($tableName)
292  ->orderBy($columnName, 'DESC')
293  ->setMaxResults(1);
294 
295  foreach ($where as $fieldName => $value) {
296  $queryBuilder->andWhere(
297  $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($value, \PDO::PARAM_STR))
298  );
299  }
300 
301  $result = $queryBuilder->execute()->fetchColumn(0);
302  } catch (DBALException $e) {
303  throw new SqlErrorException($e->getPrevious()->getMessage(), 1470230770, $e);
304  }
305  return $result;
306  }
307 
316  public function ‪getRowByIdentifier($tableName, array $where)
317  {
318  try {
319  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
320  $queryBuilder->getRestrictions()->removeAll();
321  $queryBuilder
322  ->select('*')
323  ->from($tableName);
324 
325  foreach ($where as $fieldName => $value) {
326  $queryBuilder->andWhere(
327  $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($value, \PDO::PARAM_STR))
328  );
329  }
330 
331  $row = $queryBuilder->execute()->fetch();
332  } catch (DBALException $e) {
333  throw new SqlErrorException($e->getPrevious()->getMessage(), 1470230771, $e);
334  }
335  return $row ?: false;
336  }
337 
345  public function ‪getObjectDataByQuery(QueryInterface $query)
346  {
347  $statement = $query->getStatement();
348  if ($statement instanceof Qom\Statement
349  && !$statement->getStatement() instanceof QueryBuilder
350  ) {
351  $rows = $this->‪getObjectDataByRawQuery($statement);
352  } else {
353  $queryParser = $this->objectManager->get(Typo3DbQueryParser::class);
354  if ($statement instanceof Qom\Statement
355  && $statement->getStatement() instanceof QueryBuilder
356  ) {
357  $queryBuilder = $statement->getStatement();
358  } else {
359  $queryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query);
360  }
361  $selectParts = $queryBuilder->getQueryPart('select');
362  if ($queryParser->isDistinctQuerySuggested() && !empty($selectParts)) {
363  $selectParts[0] = 'DISTINCT ' . $selectParts[0];
364  $queryBuilder->selectLiteral(...$selectParts);
365  }
366  if ($query->getOffset()) {
367  $queryBuilder->setFirstResult($query->getOffset());
368  }
369  if ($query->getLimit()) {
370  $queryBuilder->setMaxResults($query->getLimit());
371  }
372  try {
373  $rows = $queryBuilder->execute()->fetchAll();
374  } catch (DBALException $e) {
375  throw new SqlErrorException($e->getPrevious()->getMessage(), 1472074485, $e);
376  }
377  }
378 
379  if ($this->configurationManager->isFeatureEnabled('consistentTranslationOverlayHandling') && !empty($rows)) {
380  $rows = $this->‪overlayLanguageAndWorkspace($query->getSource(), $rows, $query);
381  } else {
382  $rows = $this->‪doLanguageAndWorkspaceOverlay($query->getSource(), $rows, $query->getQuerySettings());
383  }
384 
385  return $rows;
386  }
387 
395  protected function ‪getObjectDataByRawQuery(Qom\Statement $statement)
396  {
397  $realStatement = $statement->getStatement();
398  $parameters = $statement->getBoundVariables();
399 
400  // The real statement is an instance of the Doctrine DBAL QueryBuilder, so fetching
401  // this directly is possible
402  if ($realStatement instanceof QueryBuilder) {
403  try {
404  $result = $realStatement->execute();
405  } catch (DBALException $e) {
406  throw new SqlErrorException($e->getPrevious()->getMessage(), 1472064721, $e);
407  }
408  $rows = $result->fetchAll();
409  } elseif ($realStatement instanceof \Doctrine\DBAL\Statement) {
410  try {
411  $realStatement->execute($parameters);
412  } catch (DBALException $e) {
413  throw new SqlErrorException($e->getPrevious()->getMessage(), 1481281404, $e);
414  }
415  $rows = $realStatement->fetchAll();
416  } else {
417  // Do a real raw query. This is very stupid, as it does not allow to use DBAL's real power if
418  // several tables are on different databases, so this is used with caution and could be removed
419  // in the future
420  try {
421  $connection = $this->connectionPool->getConnectionByName(‪ConnectionPool::DEFAULT_CONNECTION_NAME);
422  $statement = $connection->executeQuery($realStatement, $parameters);
423  } catch (DBALException $e) {
424  throw new SqlErrorException($e->getPrevious()->getMessage(), 1472064775, $e);
425  }
426 
427  $rows = $statement->fetchAll();
428  }
429 
430  return $rows;
431  }
432 
441  public function ‪getObjectCountByQuery(QueryInterface $query)
442  {
443  if ($query->getConstraint() instanceof Qom\Statement) {
444  throw new BadConstraintException('Could not execute count on queries with a constraint of type TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Qom\\Statement', 1256661045);
445  }
446 
447  $statement = $query->getStatement();
448  if ($statement instanceof Qom\Statement
449  && !$statement->getStatement() instanceof QueryBuilder
450  ) {
451  $rows = $this->‪getObjectDataByQuery($query);
452  $count = count($rows);
453  } else {
454  $queryParser = $this->objectManager->get(Typo3DbQueryParser::class);
455  $queryBuilder = $queryParser
456  ->convertQueryToDoctrineQueryBuilder($query)
457  ->resetQueryPart('orderBy');
458 
459  if ($queryParser->isDistinctQuerySuggested()) {
460  $source = $queryBuilder->getQueryPart('from')[0];
461  // Tablename is already quoted for the DBMS, we need to treat table and field names separately
462  $tableName = $source['alias'] ?: $source['table'];
463  $fieldName = $queryBuilder->quoteIdentifier('uid');
464  $queryBuilder->resetQueryPart('groupBy')
465  ->selectLiteral(sprintf('COUNT(DISTINCT %s.%s)', $tableName, $fieldName));
466  } else {
467  $queryBuilder->count('*');
468  }
469 
470  try {
471  $count = $queryBuilder->execute()->fetchColumn(0);
472  } catch (DBALException $e) {
473  throw new SqlErrorException($e->getPrevious()->getMessage(), 1472074379, $e);
474  }
475  if ($query->getOffset()) {
476  $count -= $query->getOffset();
477  }
478  if ($query->getLimit()) {
479  $count = min($count, $query->getLimit());
480  }
481  }
482  return (int)max(0, $count);
483  }
484 
492  public function ‪getUidOfAlreadyPersistedValueObject(AbstractValueObject $object)
493  {
494  $dataMapper = $this->objectManager->get(DataMapper::class);
495  $dataMap = $dataMapper->getDataMap(get_class($object));
496  $tableName = $dataMap->getTableName();
497  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
498  if ($this->environmentService->isEnvironmentInFrontendMode()) {
499  $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
500  }
501  $whereClause = [];
502  // loop over all properties of the object to exactly set the values of each database field
503  $properties = $object->_getProperties();
504  foreach ($properties as $propertyName => $propertyValue) {
505  // @todo We couple the Backend to the Entity implementation (uid, isClone); changes there breaks this method
506  if ($dataMap->isPersistableProperty($propertyName) && $propertyName !== 'uid' && $propertyName !== 'pid' && $propertyName !== 'isClone') {
507  $fieldName = $dataMap->getColumnMap($propertyName)->getColumnName();
508  if ($propertyValue === null) {
509  $whereClause[] = $queryBuilder->expr()->isNull($fieldName);
510  } else {
511  $whereClause[] = $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($dataMapper->getPlainValue($propertyValue)));
512  }
513  }
514  }
515  $queryBuilder
516  ->select('uid')
517  ->from($tableName)
518  ->where(...$whereClause);
519 
520  try {
521  $uid = (int)$queryBuilder
522  ->execute()
523  ->fetchColumn(0);
524  if ($uid > 0) {
525  return $uid;
526  }
527  return false;
528  } catch (DBALException $e) {
529  throw new SqlErrorException($e->getPrevious()->getMessage(), 1470231748, $e);
530  }
531  }
532 
545  protected function ‪doLanguageAndWorkspaceOverlay(Qom\SourceInterface $source, array $rows, QuerySettingsInterface $querySettings, $workspaceUid = null)
546  {
547  if ($source instanceof Qom\SelectorInterface) {
548  $tableName = $source->getSelectorName();
549  } elseif ($source instanceof Qom\JoinInterface) {
550  $tableName = $source->getRight()->getSelectorName();
551  } else {
552  // No proper source, so we do not have a table name here
553  // we cannot do an overlay and return the original rows instead.
554  return $rows;
555  }
556 
557  $context = $this->objectManager->get(Context::class);
558  if ($workspaceUid === null) {
559  $workspaceUid = $context->getPropertyFromAspect('workspace', 'id');
560  } else {
561  // A custom query is needed, so a custom context is cloned
562  $workspaceUid = (int)$workspaceUid;
563  $context = clone $context;
564  $context->setAspect('workspace', $this->objectManager->get(WorkspaceAspect::class, $workspaceUid));
565  }
566  $pageRepository = $this->objectManager->get(PageRepository::class, $context);
567 
568  // Fetches the move-placeholder in case it is supported
569  // by the table and if there's only one row in the result set
570  // (applying this to all rows does not work, since the sorting
571  // order would be destroyed and possible limits not met anymore)
572  if (!empty($workspaceUid)
574  && count($rows) === 1
575  ) {
576  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
577  $queryBuilder->getRestrictions()->removeAll();
578  $movePlaceholder = $queryBuilder
579  ->select($tableName . '.*')
580  ->from($tableName)
581  ->where(
582  $queryBuilder->expr()->eq('t3ver_state', $queryBuilder->createNamedParameter(3, \PDO::PARAM_INT)),
583  $queryBuilder->expr()->eq('t3ver_wsid', $queryBuilder->createNamedParameter($workspaceUid, \PDO::PARAM_INT)),
584  $queryBuilder->expr()->eq('t3ver_move_id', $queryBuilder->createNamedParameter($rows[0]['uid'], \PDO::PARAM_INT))
585  )
586  ->setMaxResults(1)
587  ->execute()
588  ->fetch();
589  if (!empty($movePlaceholder)) {
590  $rows = [$movePlaceholder];
591  }
592  }
593 
594  $overlaidRows = [];
595  foreach ($rows as $row) {
596  // If current row is a translation select its parent
597  if (isset($tableName) && isset(‪$GLOBALS['TCA'][$tableName])
598  && isset(‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'])
599  && isset(‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
600  && isset($row[‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']])
601  && $row[‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0
602  ) {
603  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
604  $queryBuilder->getRestrictions()->removeAll();
605  $row = $queryBuilder
606  ->select($tableName . '.*')
607  ->from($tableName)
608  ->where(
609  $queryBuilder->expr()->eq(
610  $tableName . '.uid',
611  $queryBuilder->createNamedParameter(
612  $row[‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']],
613  \PDO::PARAM_INT
614  )
615  ),
616  $queryBuilder->expr()->eq(
617  $tableName . '.' . ‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'],
618  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
619  )
620  )
621  ->setMaxResults(1)
622  ->execute()
623  ->fetch();
624  }
625  $pageRepository->versionOL($tableName, $row, true);
626  if ($tableName === 'pages') {
627  $row = $pageRepository->getPageOverlay($row, $querySettings->getLanguageUid());
628  } elseif (isset(‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'])
629  && ‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== ''
630  && in_array($row[‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField']], [-1, 0])
631  ) {
632  $overlayMode = $querySettings->getLanguageMode() === 'strict' ? 'hideNonTranslated' : '';
633  $row = $pageRepository->getRecordOverlay($tableName, $row, $querySettings->getLanguageUid(), $overlayMode);
634  }
635  if (is_array($row)) {
636  $overlaidRows[] = $row;
637  }
638  }
639  return $overlaidRows;
640  }
641 
653  protected function ‪overlayLanguageAndWorkspace(Qom\SourceInterface $source, array $rows, QueryInterface $query, int $workspaceUid = null): array
654  {
655  if ($source instanceof Qom\SelectorInterface) {
656  $tableName = $source->getSelectorName();
657  } elseif ($source instanceof Qom\JoinInterface) {
658  $tableName = $source->getRight()->getSelectorName();
659  } else {
660  // No proper source, so we do not have a table name here
661  // we cannot do an overlay and return the original rows instead.
662  return $rows;
663  }
664 
665  $context = $this->objectManager->get(Context::class);
666  if ($workspaceUid === null) {
667  $workspaceUid = $context->getPropertyFromAspect('workspace', 'id');
668  } else {
669  // A custom query is needed, so a custom context is cloned
670  $workspaceUid = (int)$workspaceUid;
671  $context = clone $context;
672  $context->setAspect('workspace', $this->objectManager->get(WorkspaceAspect::class, $workspaceUid));
673  }
674  $pageRepository = $this->objectManager->get(PageRepository::class, $context);
675 
676  // Fetches the move-placeholder in case it is supported
677  // by the table and if there's only one row in the result set
678  // (applying this to all rows does not work, since the sorting
679  // order would be destroyed and possible limits not met anymore)
680  if (!empty($workspaceUid)
682  && count($rows) === 1
683  ) {
684  $versionId = $workspaceUid;
685  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
686  $queryBuilder->getRestrictions()->removeAll();
687  $movePlaceholder = $queryBuilder
688  ->select($tableName . '.*')
689  ->from($tableName)
690  ->where(
691  $queryBuilder->expr()->eq('t3ver_state', $queryBuilder->createNamedParameter(3, \PDO::PARAM_INT)),
692  $queryBuilder->expr()->eq('t3ver_wsid', $queryBuilder->createNamedParameter($versionId, \PDO::PARAM_INT)),
693  $queryBuilder->expr()->eq('t3ver_move_id', $queryBuilder->createNamedParameter($rows[0]['uid'], \PDO::PARAM_INT))
694  )
695  ->setMaxResults(1)
696  ->execute()
697  ->fetchAll();
698  if (!empty($movePlaceholder)) {
699  $rows = $movePlaceholder;
700  }
701  }
702  $overlaidRows = [];
703  foreach ($rows as $row) {
704  $pageRepository->versionOL($tableName, $row, true);
705  $querySettings = $query->getQuerySettings();
706  if (is_array($row) && $querySettings->getLanguageOverlayMode()) {
707  if ($tableName === 'pages') {
708  $row = $pageRepository->getPageOverlay($row, $querySettings->getLanguageUid());
709  } else {
710  $languageUid = (int)$querySettings->getLanguageUid();
711  if (!$querySettings->getRespectSysLanguage()
712  && isset($row[‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField']])
713  && $row[‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField']] > 0
714  && (!$query instanceof Query || !$query->getParentQuery())
715  ) {
716  //no parent query means we're processing the aggregate root.
717  //respectSysLanguage is false which means that records returned by the query
718  //might be from different languages (which is desired).
719  //So we need to force language used for overlay to the language of the current record.
720  $languageUid = $row[‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField']];
721  }
722  if (isset(‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']) && $row[‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0) {
723  //force overlay by faking default language record, as getRecordOverlay can only handle default language records
724  $row['uid'] = $row[‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']];
725  $row[‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField']] = 0;
726  }
727  $row = $pageRepository->getRecordOverlay($tableName, $row, $languageUid, (string)$querySettings->getLanguageOverlayMode());
728  }
729  }
730  if ($row !== null && is_array($row)) {
731  $overlaidRows[] = $row;
732  }
733  }
734  return $overlaidRows;
735  }
736 
747  protected function ‪clearPageCache($tableName, $uid)
748  {
749  $frameworkConfiguration = $this->configurationManager->getConfiguration(‪ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
750  if (empty($frameworkConfiguration['persistence']['enableAutomaticCacheClearing'])) {
751  return;
752  }
753  $pageIdsToClear = [];
754  $storagePage = null;
755 
756  // As determining the table columns is a costly operation this is done only once per table during runtime and cached then
757  if (!isset($this->hasPidColumn[$tableName])) {
758  $columns = GeneralUtility::makeInstance(ConnectionPool::class)
759  ->getConnectionForTable($tableName)
760  ->getSchemaManager()
761  ->listTableColumns($tableName);
762  $this->hasPidColumn[$tableName] = array_key_exists('pid', $columns);
763  }
764 
765  $tsfe = $this->‪getTSFE();
766  if ($this->hasPidColumn[$tableName]) {
767  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
768  $queryBuilder->getRestrictions()->removeAll();
769  $result = $queryBuilder
770  ->select('pid')
771  ->from($tableName)
772  ->where(
773  $queryBuilder->expr()->eq(
774  'uid',
775  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
776  )
777  )
778  ->execute();
779  if ($row = $result->fetch()) {
780  $storagePage = $row['pid'];
781  $pageIdsToClear[] = $storagePage;
782  }
783  } elseif (isset($tsfe)) {
784  // No PID column - we can do a best-effort to clear the cache of the current page if in FE
785  $storagePage = $tsfe->id;
786  $pageIdsToClear[] = $storagePage;
787  }
788  if ($storagePage === null) {
789  return;
790  }
791 
792  $pageTS = ‪BackendUtility::getPagesTSconfig($storagePage);
793  if (isset($pageTS['TCEMAIN.']['clearCacheCmd'])) {
794  $clearCacheCommands = GeneralUtility::trimExplode(',', strtolower($pageTS['TCEMAIN.']['clearCacheCmd']), true);
795  $clearCacheCommands = array_unique($clearCacheCommands);
796  foreach ($clearCacheCommands as $clearCacheCommand) {
797  if (‪MathUtility::canBeInterpretedAsInteger($clearCacheCommand)) {
798  $pageIdsToClear[] = $clearCacheCommand;
799  }
800  }
801  }
802 
803  foreach ($pageIdsToClear as $pageIdToClear) {
804  $this->cacheService->getPageIdStack()->push($pageIdToClear);
805  }
806  }
807 
811  protected function ‪getTSFE()
812  {
813  return ‪$GLOBALS['TSFE'] ?? null;
814  }
815 }
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getConstraint
‪ConstraintInterface null getConstraint()
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getLimit
‪int getLimit()
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:29
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\addRow
‪int addRow($tableName, array $fieldValues, $isRelation=false)
Definition: Typo3DbBackend.php:125
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend
Definition: Typo3DbBackend.php:48
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getOffset
‪int getOffset()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\Statement\getStatement
‪string Doctrine DBAL Statement TYPO3 CMS Core Database Query QueryBuilder getStatement()
Definition: Statement.php:48
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\getObjectDataByRawQuery
‪array getObjectDataByRawQuery(Qom\Statement $statement)
Definition: Typo3DbBackend.php:389
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\$cacheService
‪CacheService $cacheService
Definition: Typo3DbBackend.php:59
‪TYPO3\CMS\Extbase\Persistence\QueryInterface
Definition: QueryInterface.php:26
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface
Definition: SourceInterface.php:21
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:22
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
Definition: DataMapper.php:32
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\Statement
Definition: Statement.php:22
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\clearPageCache
‪clearPageCache($tableName, $uid)
Definition: Typo3DbBackend.php:741
‪TYPO3\CMS\Core\Database\ConnectionPool\DEFAULT_CONNECTION_NAME
‪const DEFAULT_CONNECTION_NAME
Definition: ConnectionPool.php:48
‪TYPO3\CMS\Extbase\Object\ObjectManagerInterface
Definition: ObjectManagerInterface.php:23
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface\CONFIGURATION_TYPE_FRAMEWORK
‪const CONFIGURATION_TYPE_FRAMEWORK
Definition: ConfigurationManagerInterface.php:23
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableWorkspaceEnabled
‪static bool isTableWorkspaceEnabled($table)
Definition: BackendUtility.php:4493
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\getObjectCountByQuery
‪int getObjectCountByQuery(QueryInterface $query)
Definition: Typo3DbBackend.php:435
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getLanguageMode
‪string getLanguageMode()
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\injectCacheService
‪injectCacheService(CacheService $cacheService)
Definition: Typo3DbBackend.php:87
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getSource
‪TYPO3 CMS Extbase Persistence Generic Qom SourceInterface getSource()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\SelectorInterface
Definition: SelectorInterface.php:29
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\$objectManager
‪ObjectManagerInterface $objectManager
Definition: Typo3DbBackend.php:67
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\getRowByIdentifier
‪array bool getRowByIdentifier($tableName, array $where)
Definition: Typo3DbBackend.php:310
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\getMaxValueFromTable
‪mixed getMaxValueFromTable($tableName, array $where, $columnName)
Definition: Typo3DbBackend.php:278
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Exception\SqlErrorException
Definition: SqlErrorException.php:21
‪TYPO3\CMS\Frontend\Page\PageRepository
Definition: PageRepository.php:53
‪TYPO3\CMS\Extbase\DomainObject\AbstractValueObject
Definition: AbstractValueObject.php:23
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\updateRow
‪bool updateRow($tableName, array $fieldValues, $isRelation=false)
Definition: Typo3DbBackend.php:167
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getLanguageUid
‪int getLanguageUid()
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\updateRelationTableRow
‪bool updateRelationTableRow($tableName, array $fieldValues)
Definition: Typo3DbBackend.php:211
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\$hasPidColumn
‪array $hasPidColumn
Definition: Typo3DbBackend.php:74
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\injectObjectManager
‪injectObjectManager(ObjectManagerInterface $objectManager)
Definition: Typo3DbBackend.php:103
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getStatement
‪TYPO3 CMS Extbase Persistence Generic Qom Statement getStatement()
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\overlayLanguageAndWorkspace
‪array overlayLanguageAndWorkspace(Qom\SourceInterface $source, array $rows, QueryInterface $query, int $workspaceUid=null)
Definition: Typo3DbBackend.php:647
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage
Definition: BackendInterface.php:2
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface
Definition: JoinInterface.php:21
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Exception\BadConstraintException
Definition: BadConstraintException.php:21
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\doLanguageAndWorkspaceOverlay
‪array doLanguageAndWorkspaceOverlay(Qom\SourceInterface $source, array $rows, QuerySettingsInterface $querySettings, $workspaceUid=null)
Definition: Typo3DbBackend.php:539
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
Definition: QuerySettingsInterface.php:21
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\getUidOfAlreadyPersistedValueObject
‪mixed getUidOfAlreadyPersistedValueObject(AbstractValueObject $object)
Definition: Typo3DbBackend.php:486
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Extbase\Service\EnvironmentService
Definition: EnvironmentService.php:24
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\_getProperties
‪array _getProperties()
Definition: AbstractDomainObject.php:129
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom
Definition: AndInterface.php:2
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\$environmentService
‪EnvironmentService $environmentService
Definition: Typo3DbBackend.php:63
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getQuerySettings
‪TYPO3 CMS Extbase Persistence Generic QuerySettingsInterface getQuerySettings()
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\$configurationManager
‪ConfigurationManagerInterface $configurationManager
Definition: Typo3DbBackend.php:55
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:97
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
Definition: BackendUtility.php:864
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Extbase\Service\CacheService
Definition: CacheService.php:22
‪TYPO3\CMS\Extbase\Persistence\Generic\Query
Definition: Query.php:23
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\getTSFE
‪TypoScriptFrontendController null getTSFE()
Definition: Typo3DbBackend.php:805
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\BackendInterface
Definition: BackendInterface.php:21
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\injectEnvironmentService
‪injectEnvironmentService(EnvironmentService $environmentService)
Definition: Typo3DbBackend.php:95
‪TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer
Definition: FrontendRestrictionContainer.php:29
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\getObjectDataByQuery
‪array getObjectDataByQuery(QueryInterface $query)
Definition: Typo3DbBackend.php:339
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\__construct
‪__construct()
Definition: Typo3DbBackend.php:111
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\$connectionPool
‪ConnectionPool $connectionPool
Definition: Typo3DbBackend.php:51
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\removeRow
‪bool removeRow($tableName, array $where, $isRelation=false)
Definition: Typo3DbBackend.php:253
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend\injectConfigurationManager
‪injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
Definition: Typo3DbBackend.php:79