[BUGFIX] Fix wrong query in DataHandlerHook
[Packages/TYPO3.CMS.git] / typo3 / sysext / workspaces / Classes / Hook / DataHandlerHook.php
1 <?php
2 namespace TYPO3\CMS\Workspaces\Hook;
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\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Database\ConnectionPool;
19 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
20 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Workspaces\Service\StagesService;
23
24 /**
25 * Tcemain service
26 */
27 class DataHandlerHook
28 {
29 /**
30 * In case a sys_workspace_stage record is deleted we do a hard reset
31 * for all existing records in that stage to avoid that any of these end up
32 * as orphan records.
33 *
34 * @param string $command
35 * @param string $table
36 * @param string $id
37 * @param string $value
38 * @param \TYPO3\CMS\Core\DataHandling\DataHandler $tcemain
39 * @return void
40 */
41 public function processCmdmap_postProcess($command, $table, $id, $value, \TYPO3\CMS\Core\DataHandling\DataHandler $tcemain)
42 {
43 if ($command === 'delete') {
44 if ($table === StagesService::TABLE_STAGE) {
45 $this->resetStageOfElements($id);
46 } elseif ($table === \TYPO3\CMS\Workspaces\Service\WorkspaceService::TABLE_WORKSPACE) {
47 $this->flushWorkspaceElements($id);
48 }
49 }
50 }
51
52 /**
53 * hook that is called AFTER all commands of the commandmap was
54 * executed
55 *
56 * @param \TYPO3\CMS\Core\DataHandling\DataHandler $tcemainObj reference to the main tcemain object
57 * @return void
58 */
59 public function processCmdmap_afterFinish(\TYPO3\CMS\Core\DataHandling\DataHandler $tcemainObj)
60 {
61 $this->flushWorkspaceCacheEntriesByWorkspaceId($tcemainObj->BE_USER->workspace);
62 }
63
64 /**
65 * In case a sys_workspace_stage record is deleted we do a hard reset
66 * for all existing records in that stage to avoid that any of these end up
67 * as orphan records.
68 *
69 * @param int $stageId Elements with this stage are resetted
70 * @return void
71 */
72 protected function resetStageOfElements($stageId)
73 {
74 foreach ($this->getTcaTables() as $tcaTable) {
75 if (BackendUtility::isTableWorkspaceEnabled($tcaTable)) {
76 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
77 ->getQueryBuilderForTable($tcaTable);
78
79 $queryBuilder
80 ->update($tcaTable)
81 ->set('t3ver_stage', StagesService::STAGE_EDIT_ID)
82 ->where(
83 $queryBuilder->expr()->eq('t3ver_stage', (int)$stageId),
84 $queryBuilder->expr()->eq('pid', -1),
85 $queryBuilder->expr()->gt('t3ver_wsid', 0)
86 )
87 ->execute();
88 }
89 }
90 }
91
92 /**
93 * Flushes elements of a particular workspace to avoid orphan records.
94 *
95 * @param int $workspaceId The workspace to be flushed
96 * @return void
97 */
98 protected function flushWorkspaceElements($workspaceId)
99 {
100 $command = [];
101 foreach ($this->getTcaTables() as $tcaTable) {
102 if (BackendUtility::isTableWorkspaceEnabled($tcaTable)) {
103 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
104 ->getQueryBuilderForTable($tcaTable);
105 $queryBuilder->getRestrictions()
106 ->removeAll()
107 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
108 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, $workspaceId, false));
109
110 $result = $queryBuilder
111 ->select('uid')
112 ->from($tcaTable)
113 ->orderBy('uid')
114 ->execute();
115
116 while (($recordId = $result->fetchColumn()) !== false) {
117 $command[$tcaTable][$recordId]['version']['action'] = 'flush';
118 }
119 }
120 }
121 if (!empty($command)) {
122 $tceMain = $this->getTceMain();
123 $tceMain->start([], $command);
124 $tceMain->process_cmdmap();
125 }
126 }
127
128 /**
129 * Gets all defined TCA tables.
130 *
131 * @return array
132 */
133 protected function getTcaTables()
134 {
135 return array_keys($GLOBALS['TCA']);
136 }
137
138 /**
139 * @return \TYPO3\CMS\Core\DataHandling\DataHandler
140 */
141 protected function getTceMain()
142 {
143 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
144 }
145
146 /**
147 * Flushes the workspace cache for current workspace and for the virtual "all workspaces" too.
148 *
149 * @param int $workspaceId The workspace to be flushed in cache
150 * @return void
151 */
152 protected function flushWorkspaceCacheEntriesByWorkspaceId($workspaceId)
153 {
154 $workspacesCache = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('workspaces_cache');
155 $workspacesCache->flushByTag($workspaceId);
156 $workspacesCache->flushByTag(\TYPO3\CMS\Workspaces\Service\WorkspaceService::SELECT_ALL_WORKSPACES);
157 }
158 }