Conditions | 21 |
Paths | 1381 |
Total Lines | 143 |
Code Lines | 83 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php |
||
132 | public function executeUpdate(): bool |
||
133 | { |
||
134 | $registry = GeneralUtility::makeInstance(Registry::class); |
||
135 | |||
136 | // If rows from the target table that is updated and the sys_registry table are on the |
||
137 | // same connection, the row update statement and sys_registry position update will be |
||
138 | // handled in a transaction to have an atomic operation in case of errors during execution. |
||
139 | $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); |
||
140 | $connectionForSysRegistry = $connectionPool->getConnectionForTable('sys_registry'); |
||
141 | |||
142 | /** @var RowUpdaterInterface[] $rowUpdaterInstances */ |
||
143 | $rowUpdaterInstances = []; |
||
144 | // Single row updater instances are created only once for this method giving |
||
145 | // them a chance to set up local properties during hasPotentialUpdateForTable() |
||
146 | // and using that in updateTableRow() |
||
147 | foreach ($this->getRowUpdatersToExecute() as $rowUpdater) { |
||
148 | $rowUpdaterInstance = GeneralUtility::makeInstance($rowUpdater); |
||
149 | if (!$rowUpdaterInstance instanceof RowUpdaterInterface) { |
||
150 | throw new \RuntimeException( |
||
151 | 'Row updater must implement RowUpdaterInterface', |
||
152 | 1484071612 |
||
153 | ); |
||
154 | } |
||
155 | $rowUpdaterInstances[] = $rowUpdaterInstance; |
||
156 | } |
||
157 | |||
158 | // Scope of the row updater is to update all rows that have TCA, |
||
159 | // our list of tables is just the list of loaded TCA tables. |
||
160 | /** @var string[] $listOfAllTables */ |
||
161 | $listOfAllTables = array_keys($GLOBALS['TCA']); |
||
162 | |||
163 | // In case the PHP ended for whatever reason, fetch the last position from registry |
||
164 | // and throw away all tables before that start point. |
||
165 | sort($listOfAllTables); |
||
166 | reset($listOfAllTables); |
||
167 | $firstTable = current($listOfAllTables) ?: ''; |
||
168 | $startPosition = $this->getStartPosition($firstTable); |
||
169 | foreach ($listOfAllTables as $key => $table) { |
||
170 | if ($table === $startPosition['table']) { |
||
171 | break; |
||
172 | } |
||
173 | unset($listOfAllTables[$key]); |
||
174 | } |
||
175 | |||
176 | // Ask each row updater if it potentially has field updates for rows of a table |
||
177 | $tableToUpdaterList = []; |
||
178 | foreach ($listOfAllTables as $table) { |
||
179 | foreach ($rowUpdaterInstances as $updater) { |
||
180 | if ($updater->hasPotentialUpdateForTable($table)) { |
||
181 | if (!isset($tableToUpdaterList[$table]) || !is_array($tableToUpdaterList[$table])) { |
||
182 | $tableToUpdaterList[$table] = []; |
||
183 | } |
||
184 | $tableToUpdaterList[$table][] = $updater; |
||
185 | } |
||
186 | } |
||
187 | } |
||
188 | |||
189 | // Iterate through all rows of all tables that have potential row updaters attached, |
||
190 | // feed each single row to each updater and finally update each row in database if |
||
191 | // a row updater changed a fields |
||
192 | foreach ($tableToUpdaterList as $table => $updaters) { |
||
193 | /** @var RowUpdaterInterface[] $updaters */ |
||
194 | $connectionForTable = $connectionPool->getConnectionForTable($table); |
||
195 | $queryBuilder = $connectionPool->getQueryBuilderForTable($table); |
||
196 | $queryBuilder->getRestrictions()->removeAll(); |
||
197 | $queryBuilder->select('*') |
||
198 | ->from($table) |
||
199 | ->orderBy('uid'); |
||
200 | if ($table === $startPosition['table']) { |
||
201 | $queryBuilder->where( |
||
202 | $queryBuilder->expr()->gt('uid', $queryBuilder->createNamedParameter($startPosition['uid'])) |
||
203 | ); |
||
204 | } |
||
205 | $statement = $queryBuilder->execute(); |
||
206 | $rowCountWithoutUpdate = 0; |
||
207 | while ($row = $rowBefore = $statement->fetch()) { |
||
208 | foreach ($updaters as $updater) { |
||
209 | $row = $updater->updateTableRow($table, $row); |
||
210 | } |
||
211 | $updatedFields = array_diff_assoc($row, $rowBefore); |
||
212 | if (empty($updatedFields)) { |
||
213 | // Updaters changed no field of that row |
||
214 | $rowCountWithoutUpdate++; |
||
215 | if ($rowCountWithoutUpdate >= 200) { |
||
216 | // Update startPosition if there were many rows without data change |
||
217 | $startPosition = [ |
||
218 | 'table' => $table, |
||
219 | 'uid' => $row['uid'], |
||
220 | ]; |
||
221 | $registry->set('installUpdateRows', 'rowUpdatePosition', $startPosition); |
||
222 | $rowCountWithoutUpdate = 0; |
||
223 | } |
||
224 | } else { |
||
225 | $rowCountWithoutUpdate = 0; |
||
226 | $startPosition = [ |
||
227 | 'table' => $table, |
||
228 | 'uid' => $rowBefore['uid'], |
||
229 | ]; |
||
230 | if ($connectionForSysRegistry === $connectionForTable |
||
231 | && !($connectionForSysRegistry->getDatabasePlatform() instanceof SQLServerPlatform) |
||
232 | ) { |
||
233 | // Target table and sys_registry table are on the same connection and not mssql, use a transaction |
||
234 | $connectionForTable->beginTransaction(); |
||
235 | try { |
||
236 | $this->updateOrDeleteRow( |
||
237 | $connectionForTable, |
||
238 | $connectionForTable, |
||
239 | $table, |
||
240 | (int)$rowBefore['uid'], |
||
241 | $updatedFields, |
||
242 | $startPosition |
||
243 | ); |
||
244 | $connectionForTable->commit(); |
||
245 | } catch (\Exception $up) { |
||
246 | $connectionForTable->rollBack(); |
||
247 | throw $up; |
||
248 | } |
||
249 | } else { |
||
250 | // Either different connections for table and sys_registry, or mssql. |
||
251 | // SqlServer can not run a transaction for a table if the same table is queried |
||
252 | // currently - our above ->fetch() main loop. |
||
253 | // So, execute two distinct queries and hope for the best. |
||
254 | $this->updateOrDeleteRow( |
||
255 | $connectionForTable, |
||
256 | $connectionForSysRegistry, |
||
257 | $table, |
||
258 | (int)$rowBefore['uid'], |
||
259 | $updatedFields, |
||
260 | $startPosition |
||
261 | ); |
||
262 | } |
||
263 | } |
||
264 | } |
||
265 | } |
||
266 | |||
267 | // Ready with updates, remove position information from sys_registry |
||
268 | $registry->remove('installUpdateRows', 'rowUpdatePosition'); |
||
269 | // Mark row updaters that were executed as done |
||
270 | foreach ($rowUpdaterInstances as $updater) { |
||
271 | $this->setRowUpdaterExecuted($updater); |
||
272 | } |
||
273 | |||
274 | return true; |
||
275 | } |
||
367 |