Conditions | 18 |
Paths | 1501 |
Total Lines | 156 |
Code Lines | 86 |
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 |
||
101 | public function performUpdate(array &$databaseQueries, &$customMessage) |
||
102 | { |
||
103 | $registry = GeneralUtility::makeInstance(Registry::class); |
||
104 | |||
105 | // If rows from the target table that is updated and the sys_registry table are on the |
||
106 | // same connection, the row update statement and sys_registry position update will be |
||
107 | // handled in a transaction to have an atomic operation in case of errors during execution. |
||
108 | $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); |
||
109 | $connectionForSysRegistry = $connectionPool->getConnectionForTable('sys_registry'); |
||
110 | |||
111 | /** @var RowUpdaterInterface[] $rowUpdaterInstances */ |
||
112 | $rowUpdaterInstances = []; |
||
113 | // Single row updater instances are created only once for this method giving |
||
114 | // them a chance to set up local properties during hasPotentialUpdateForTable() |
||
115 | // and using that in updateTableRow() |
||
116 | foreach ($this->getRowUpdatersToExecute() as $rowUpdater) { |
||
117 | $rowUpdaterInstance = GeneralUtility::makeInstance($rowUpdater); |
||
118 | if (!$rowUpdaterInstance instanceof RowUpdaterInterface) { |
||
119 | throw new \RuntimeException( |
||
120 | 'Row updater must implement RowUpdaterInterface', |
||
121 | 1484071612 |
||
122 | ); |
||
123 | } |
||
124 | $rowUpdaterInstances[] = $rowUpdaterInstance; |
||
125 | } |
||
126 | |||
127 | // Scope of the row updater is to update all rows that have TCA, |
||
128 | // our list of tables is just the list of loaded TCA tables. |
||
129 | $listOfAllTables = array_keys($GLOBALS['TCA']); |
||
130 | |||
131 | // In case the PHP ended for whatever reason, fetch the last position from registry |
||
132 | // and throw away all tables before that start point. |
||
133 | sort($listOfAllTables); |
||
134 | reset($listOfAllTables); |
||
135 | $firstTable = current($listOfAllTables); |
||
136 | $startPosition = $this->getStartPosition($firstTable); |
||
137 | foreach ($listOfAllTables as $key => $table) { |
||
138 | if ($table === $startPosition['table']) { |
||
139 | break; |
||
140 | } |
||
141 | unset($listOfAllTables[$key]); |
||
142 | } |
||
143 | |||
144 | // Ask each row updater if it potentially has field updates for rows of a table |
||
145 | $tableToUpdaterList = []; |
||
146 | foreach ($listOfAllTables as $table) { |
||
147 | foreach ($rowUpdaterInstances as $updater) { |
||
148 | if ($updater->hasPotentialUpdateForTable($table)) { |
||
149 | if (!is_array($tableToUpdaterList[$table])) { |
||
150 | $tableToUpdaterList[$table] = []; |
||
151 | } |
||
152 | $tableToUpdaterList[$table][] = $updater; |
||
153 | } |
||
154 | } |
||
155 | } |
||
156 | |||
157 | // Iterate through all rows of all tables that have potential row updaters attached, |
||
158 | // feed each single row to each updater and finally update each row in database if |
||
159 | // a row updater changed a fields |
||
160 | foreach ($tableToUpdaterList as $table => $updaters) { |
||
161 | /** @var RowUpdaterInterface[] $updaters */ |
||
162 | $connectionForTable = $connectionPool->getConnectionForTable($table); |
||
163 | $queryBuilder = $connectionPool->getQueryBuilderForTable($table); |
||
164 | $queryBuilder->getRestrictions()->removeAll(); |
||
165 | $queryBuilder->select('*') |
||
166 | ->from($table) |
||
167 | ->orderBy('uid'); |
||
168 | if ($table === $startPosition['table']) { |
||
169 | $queryBuilder->where( |
||
170 | $queryBuilder->expr()->gt('uid', $queryBuilder->createNamedParameter($startPosition['uid'])) |
||
171 | ); |
||
172 | } |
||
173 | $statement = $queryBuilder->execute(); |
||
174 | $rowCountWithoutUpdate = 0; |
||
175 | while ($row = $rowBefore = $statement->fetch()) { |
||
176 | foreach ($updaters as $updater) { |
||
177 | $row = $updater->updateTableRow($table, $row); |
||
178 | } |
||
179 | $updatedFields = array_diff_assoc($row, $rowBefore); |
||
180 | if (empty($updatedFields)) { |
||
181 | // Updaters changed no field of that row |
||
182 | $rowCountWithoutUpdate ++; |
||
183 | if ($rowCountWithoutUpdate >= 200) { |
||
184 | // Update startPosition if there were many rows without data change |
||
185 | $startPosition = [ |
||
186 | 'table' => $table, |
||
187 | 'uid' => $row['uid'], |
||
188 | ]; |
||
189 | $registry->set('installUpdateRows', 'rowUpdatePosition', $startPosition); |
||
190 | $rowCountWithoutUpdate = 0; |
||
191 | } |
||
192 | } else { |
||
193 | $rowCountWithoutUpdate = 0; |
||
194 | $startPosition = [ |
||
195 | 'table' => $table, |
||
196 | 'uid' => $rowBefore['uid'], |
||
197 | ]; |
||
198 | if ($connectionForSysRegistry === $connectionForTable) { |
||
199 | // Target table and sys_registry table are on the same connection, use a transaction |
||
200 | $connectionForTable->beginTransaction(); |
||
201 | try { |
||
202 | $connectionForTable->update( |
||
203 | $table, |
||
204 | $updatedFields, |
||
205 | [ |
||
206 | 'uid' => $rowBefore['uid'], |
||
207 | ] |
||
208 | ); |
||
209 | $connectionForTable->update( |
||
210 | 'sys_registry', |
||
211 | [ |
||
212 | 'entry_value' => serialize($startPosition), |
||
213 | ], |
||
214 | [ |
||
215 | 'entry_namespace' => 'installUpdateRows', |
||
216 | 'entry_key' => 'rowUpdatePosition', |
||
217 | ] |
||
218 | ); |
||
219 | $connectionForTable->commit(); |
||
220 | } catch (\Exception $up) { |
||
221 | $connectionForTable->rollBack(); |
||
222 | throw $up; |
||
223 | } |
||
224 | } else { |
||
225 | // Different connections for table and sys_registry -> execute two |
||
226 | // distinct queries and hope for the best. |
||
227 | $connectionForTable->update( |
||
228 | $table, |
||
229 | $updatedFields, |
||
230 | [ |
||
231 | 'uid' => $rowBefore['uid'], |
||
232 | ] |
||
233 | ); |
||
234 | $connectionForSysRegistry->update( |
||
235 | 'sys_registry', |
||
236 | [ |
||
237 | 'entry_value' => serialize($startPosition), |
||
238 | ], |
||
239 | [ |
||
240 | 'entry_namespace' => 'installUpdateRows', |
||
241 | 'entry_key' => 'rowUpdatePosition', |
||
242 | ] |
||
243 | ); |
||
244 | } |
||
245 | } |
||
246 | } |
||
247 | } |
||
248 | |||
249 | // Ready with updates, remove position information from sys_registry |
||
250 | $registry->remove('installUpdateRows', 'rowUpdatePosition'); |
||
251 | // Mark row updaters that were executed as done |
||
252 | foreach ($rowUpdaterInstances as $updater) { |
||
253 | $this->setRowUpdaterExecuted($updater); |
||
254 | } |
||
255 | |||
256 | return true; |
||
257 | } |
||
304 |