‪TYPO3CMS  10.4
PlainDataResolver.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
25 
34 {
38  protected ‪$tableName;
39 
43  protected ‪$liveIds;
44 
48  protected ‪$sortingStatement;
49 
53  protected ‪$workspaceId;
54 
58  protected ‪$keepLiveIds = false;
59 
63  protected ‪$keepDeletePlaceholder = false;
64 
68  protected ‪$keepMovePlaceholder = true;
69 
75  public function ‪__construct(‪$tableName, array ‪$liveIds, array ‪$sortingStatement = null)
76  {
77  $this->tableName = ‪$tableName;
78  $this->liveIds = $this->‪reindex($this->‪sanitizeIds($liveIds));
79  $this->sortingStatement = ‪$sortingStatement;
80  }
81 
87  public function ‪setWorkspaceId(‪$workspaceId)
88  {
89  $this->workspaceId = (int)‪$workspaceId;
90  }
91 
98  public function ‪setKeepLiveIds(‪$keepLiveIds)
99  {
100  $this->keepLiveIds = (bool)‪$keepLiveIds;
101  return $this;
102  }
103 
111  {
112  $this->keepDeletePlaceholder = (bool)‪$keepDeletePlaceholder;
113  return $this;
114  }
115 
123  {
124  $this->keepMovePlaceholder = (bool)‪$keepMovePlaceholder;
125  return $this;
126  }
127 
131  public function get()
132  {
133  $resolvedIds = $this->‪processVersionOverlays($this->liveIds);
134  if ($resolvedIds !== $this->liveIds) {
135  $resolvedIds = $this->‪reindex($resolvedIds);
136  }
137 
138  $tempIds = $this->‪processSorting($resolvedIds);
139  if ($tempIds !== $resolvedIds) {
140  $resolvedIds = $this->‪reindex($tempIds);
141  }
142 
143  $tempIds = $this->‪applyLiveIds($resolvedIds);
144  if ($tempIds !== $resolvedIds) {
145  $resolvedIds = $this->‪reindex($tempIds);
146  }
147 
148  return $resolvedIds;
149  }
150 
158  public function ‪processVersionOverlays(array $ids)
159  {
160  $ids = $this->‪sanitizeIds($ids);
161  if (empty($this->workspaceId) || !$this->‪isWorkspaceEnabled() || empty($ids)) {
162  return $ids;
163  }
164 
165  $ids = $this->‪reindex(
167  );
168  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
169  ->getQueryBuilderForTable($this->tableName);
170 
171  $queryBuilder->getRestrictions()->removeAll()
172  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
173 
174  $result = $queryBuilder
175  ->select('uid', 't3ver_oid', 't3ver_state')
176  ->from($this->tableName)
177  ->where(
178  $queryBuilder->expr()->in(
179  't3ver_oid',
180  $queryBuilder->createNamedParameter($ids, Connection::PARAM_INT_ARRAY)
181  ),
182  $queryBuilder->expr()->eq(
183  't3ver_wsid',
184  $queryBuilder->createNamedParameter($this->workspaceId, \PDO::PARAM_INT)
185  )
186  )
187  ->execute();
188 
189  while ($version = $result->fetch()) {
190  $liveReferenceId = $version['t3ver_oid'];
191  $versionId = $version['uid'];
192  if (isset($ids[$liveReferenceId])) {
193  if (!$this->keepDeletePlaceholder
194  && ‪VersionState::cast($version['t3ver_state'])->equals(‪VersionState::DELETE_PLACEHOLDER)
195  ) {
196  unset($ids[$liveReferenceId]);
197  } else {
198  $ids[$liveReferenceId] = $versionId;
199  }
200  }
201  }
202 
203  return $ids;
204  }
205 
213  public function ‪processVersionMovePlaceholders(array $ids)
214  {
215  $ids = $this->‪sanitizeIds($ids);
216  // Early return on insufficient data-set
217  if (empty($this->workspaceId) || !$this->‪isWorkspaceEnabled() || empty($ids)) {
218  return $ids;
219  }
220 
221  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
222  ->getQueryBuilderForTable($this->tableName);
223 
224  $queryBuilder->getRestrictions()->removeAll()
225  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
226 
227  $result = $queryBuilder
228  ->select('uid', 't3ver_move_id')
229  ->from($this->tableName)
230  ->where(
231  $queryBuilder->expr()->eq(
232  't3ver_state',
233  $queryBuilder->createNamedParameter((string)‪VersionState::MOVE_PLACEHOLDER, \PDO::PARAM_INT)
234  ),
235  $queryBuilder->expr()->eq(
236  't3ver_wsid',
237  $queryBuilder->createNamedParameter($this->workspaceId, \PDO::PARAM_INT)
238  ),
239  $queryBuilder->expr()->in(
240  't3ver_move_id',
241  $queryBuilder->createNamedParameter($ids, Connection::PARAM_INT_ARRAY)
242  )
243  )
244  ->execute();
245 
246  while ($movePlaceholder = $result->fetch()) {
247  $liveReferenceId = $movePlaceholder['t3ver_move_id'];
248  $movePlaceholderId = $movePlaceholder['uid'];
249  // Substitute MOVE_PLACEHOLDER and purge live reference
250  if (isset($ids[$movePlaceholderId])) {
251  $ids[$movePlaceholderId] = $liveReferenceId;
252  unset($ids[$liveReferenceId]);
253  } elseif (!$this->keepMovePlaceholder) {
254  // Just purge live reference
255  unset($ids[$liveReferenceId]);
256  }
257  }
258 
259  return $ids;
260  }
261 
270  public function ‪processSorting(array $ids)
271  {
272  $ids = $this->‪sanitizeIds($ids);
273  // Early return on missing sorting statement or insufficient data-set
274  if (empty($this->sortingStatement) || count($ids) < 2) {
275  return $ids;
276  }
277 
278  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
279  ->getQueryBuilderForTable($this->tableName);
280 
281  // @todo: DeletedRestriction should be added here, too. This however currently makes test
282  // workspaces/Tests/Functional/DataHandling/FAL/Publish/ActionTest::modifyContentAndDeleteFileReference
283  // fail with postgres. Suspected reason: On publish, there seems to be a missing RefenenceIndex->updateRefIndexTable()
284  // call, so sys_refindex still has relations to workspace records that don't exist anymore after publish. If that
285  // is solved and old sys_refindex relations are correctly dropped, the DeletedRestriction should be added here.
286  $queryBuilder->getRestrictions()->removeAll();
287 
288  $queryBuilder
289  ->select('uid')
290  ->from($this->tableName)
291  ->where(
292  $queryBuilder->expr()->in(
293  'uid',
294  // do not use named parameter here as the list can get too long
295  array_map('intval', $ids)
296  )
297  );
298 
299  if (!empty($this->sortingStatement)) {
300  foreach ($this->sortingStatement as ‪$sortingStatement) {
301  $queryBuilder->add('orderBy', ‪$sortingStatement, true);
302  }
303  }
304 
305  $sortedIds = $queryBuilder->execute()->fetchAll();
306 
307  return array_map('intval', array_column($sortedIds, 'uid'));
308  }
309 
319  public function ‪applyLiveIds(array $ids)
320  {
321  $ids = $this->‪sanitizeIds($ids);
322  if (!$this->keepLiveIds || !$this->‪isWorkspaceEnabled() || empty($ids)) {
323  return $ids;
324  }
325 
326  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
327  ->getQueryBuilderForTable($this->tableName);
328 
329  $queryBuilder->getRestrictions()->removeAll()
330  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
331 
332  $result = $queryBuilder
333  ->select('uid', 't3ver_oid')
334  ->from($this->tableName)
335  ->where(
336  $queryBuilder->expr()->in(
337  'uid',
338  $queryBuilder->createNamedParameter($ids, Connection::PARAM_INT_ARRAY)
339  )
340  )
341  ->execute();
342 
343  $versionIds = [];
344  while ($record = $result->fetch()) {
345  $liveId = $record['uid'];
346  $versionIds[$liveId] = $record['t3ver_oid'];
347  }
348 
349  foreach ($ids as $id) {
350  if (!empty($versionIds[$id])) {
351  $ids[$id] = $versionIds[$id];
352  }
353  }
354 
355  return $ids;
356  }
357 
364  protected function ‪reindex(array $ids)
365  {
366  if (empty($ids)) {
367  return $ids;
368  }
369  $ids = array_values($ids);
370  $ids = array_combine($ids, $ids);
371  return $ids;
372  }
373 
380  protected function ‪sanitizeIds(array $ids): array
381  {
382  return array_filter($ids);
383  }
384 
388  protected function ‪isWorkspaceEnabled()
389  {
390  if (‪ExtensionManagementUtility::isLoaded('workspaces')) {
391  return ‪BackendUtility::isTableWorkspaceEnabled($this->tableName);
392  }
393  return false;
394  }
395 }
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\processVersionOverlays
‪int[] processVersionOverlays(array $ids)
Definition: PlainDataResolver.php:151
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver
Definition: PlainDataResolver.php:34
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\__construct
‪__construct($tableName, array $liveIds, array $sortingStatement=null)
Definition: PlainDataResolver.php:68
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\$keepDeletePlaceholder
‪bool $keepDeletePlaceholder
Definition: PlainDataResolver.php:57
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\sanitizeIds
‪array sanitizeIds(array $ids)
Definition: PlainDataResolver.php:373
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\$keepMovePlaceholder
‪bool $keepMovePlaceholder
Definition: PlainDataResolver.php:61
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\setKeepMovePlaceholder
‪PlainDataResolver setKeepMovePlaceholder($keepMovePlaceholder)
Definition: PlainDataResolver.php:115
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\processSorting
‪int[] processSorting(array $ids)
Definition: PlainDataResolver.php:263
‪TYPO3\CMS\Core\DataHandling
Definition: DataHandler.php:16
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\applyLiveIds
‪int[] applyLiveIds(array $ids)
Definition: PlainDataResolver.php:312
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:55
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\processVersionMovePlaceholders
‪int[] processVersionMovePlaceholders(array $ids)
Definition: PlainDataResolver.php:206
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableWorkspaceEnabled
‪static bool isTableWorkspaceEnabled($table)
Definition: BackendUtility.php:4021
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\$tableName
‪string $tableName
Definition: PlainDataResolver.php:37
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\$sortingStatement
‪array $sortingStatement
Definition: PlainDataResolver.php:45
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\setKeepDeletePlaceholder
‪PlainDataResolver setKeepDeletePlaceholder($keepDeletePlaceholder)
Definition: PlainDataResolver.php:103
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\reindex
‪int[] reindex(array $ids)
Definition: PlainDataResolver.php:357
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\setKeepLiveIds
‪PlainDataResolver setKeepLiveIds($keepLiveIds)
Definition: PlainDataResolver.php:91
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:24
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\$workspaceId
‪int $workspaceId
Definition: PlainDataResolver.php:49
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\isWorkspaceEnabled
‪bool isWorkspaceEnabled()
Definition: PlainDataResolver.php:381
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\$liveIds
‪int[] $liveIds
Definition: PlainDataResolver.php:41
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\setWorkspaceId
‪setWorkspaceId($workspaceId)
Definition: PlainDataResolver.php:80
‪TYPO3\CMS\Core\DataHandling\PlainDataResolver\$keepLiveIds
‪bool $keepLiveIds
Definition: PlainDataResolver.php:53
‪TYPO3\CMS\Core\Versioning\VersionState\MOVE_PLACEHOLDER
‪const MOVE_PLACEHOLDER
Definition: VersionState.php:72