| 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 |