2 declare(strict_types = 1);
45 return 'separateSysHistoryFromLog';
53 return 'Migrates existing sys_log entries into sys_history';
61 return 'The history of changes of a record is now solely stored within sys_history.'
62 .
' Previous data within sys_log needs to be migrated into sys_history now.';
78 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
79 ->getQueryBuilderForTable(
'sys_history');
80 $queryBuilder->getRestrictions()->removeAll();
81 $count = $queryBuilder->count(
'*')
83 ->where($queryBuilder->expr()->neq(
'sys_log_uid', 0))
96 DatabaseUpdatedPrerequisite::class
113 $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
114 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(
'sys_history');
115 $connectionForSysRegistry = $connectionPool->getConnectionForTable(
'sys_registry');
121 if ($startPositionAndPhase[
'phase'] === self::MOVE_DATA) {
124 $connectionForSysRegistry,
125 $startPositionAndPhase
129 if ($startPositionAndPhase[
'phase'] === self::UPDATE_HISTORY) {
131 $connectionForSysRegistry,
132 $startPositionAndPhase
150 array $startPositionAndPhase
157 $rows = $queryBuilder->
select(
'sys_history.uid AS history_uid',
'sys_history.history_data',
'sys_log.*')
158 ->
from(
'sys_history')
163 $queryBuilder->expr()->eq(
'sys_history.sys_log_uid', $queryBuilder->quoteIdentifier(
'sys_log.uid'))
165 ->
where($queryBuilder->expr()->gt(
'sys_history.uid', $queryBuilder->createNamedParameter($startPositionAndPhase[
'uid'])))
167 ->
orderBy(
'sys_history.uid',
'ASC')
171 foreach ($rows as $row) {
177 'userid' => $row[
'userid'],
179 'history_data' => json_encode($historyData),
180 'originaluserid' => empty($logData[
'originalUser']) ? null : $logData[
'originalUser']
183 if ($connection === $connectionForSysRegistry) {
185 $connection->beginTransaction();
194 $connection->commit();
196 $connection->rollBack();
204 $connectionForSysRegistry,
214 }
while ($processedRows === self::BATCH_SIZE);
217 $registry = GeneralUtility::makeInstance(Registry::class);
218 $startPositionAndPhase = [
222 $registry->set(
'installSeparateHistoryFromSysLog',
'phaseAndPosition', $startPositionAndPhase);
224 return $startPositionAndPhase;
249 [
'uid' => (
int)$row[
'history_uid']],
254 $logData[
'history'] = $row[
'history_uid'];
257 [
'log_data' => serialize($logData)],
258 [
'uid' => (
int)$row[
'uid']],
261 $startPositionAndPhase = [
263 'uid' => $row[
'history_uid'],
265 $connectionForSysRegistry->
update(
268 'entry_value' => serialize($startPositionAndPhase)
271 'entry_namespace' =>
'installSeparateHistoryFromSysLog',
272 'entry_key' =>
'phaseAndPosition',
276 return $startPositionAndPhase;
287 array $startPositionAndPhase
293 $logQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'sys_log');
294 $result = $logQueryBuilder->select(
'uid',
'userid',
'action',
'tstamp',
'log_data',
'tablename',
'recuid')
297 $logQueryBuilder->expr()->eq(
'type', $logQueryBuilder->createNamedParameter(1, \PDO::PARAM_INT)),
298 $logQueryBuilder->expr()->orX(
299 $logQueryBuilder->expr()->eq(
'action', $logQueryBuilder->createNamedParameter(1, \PDO::PARAM_INT)),
300 $logQueryBuilder->expr()->eq(
'action', $logQueryBuilder->createNamedParameter(3, \PDO::PARAM_INT))
304 $logQueryBuilder->expr()->gt(
'uid', $logQueryBuilder->createNamedParameter($startPositionAndPhase[
'uid']))
306 ->orderBy(
'uid',
'ASC')
307 ->setMaxResults(self::BATCH_SIZE)
310 foreach ($result as $row) {
312 $store = GeneralUtility::makeInstance(
313 RecordHistoryStore::class,
316 (empty($logData[
'originalUser']) ?
null : $logData[
'originalUser']),
320 switch ($row[
'action']) {
323 $store->addRecord($row[
'tablename'], (
int)$row[
'recuid'], $logData);
327 $store->deleteRecord($row[
'tablename'], (
int)$row[
'recuid']);
331 $startPositionAndPhase = [
333 'uid' => $row[
'uid'],
335 $connectionForSysRegistry->
update(
338 'entry_value' => serialize($startPositionAndPhase)
341 'entry_namespace' =>
'installSeparateHistoryFromSysLog',
342 'entry_key' =>
'phaseAndPosition',
349 }
while ($processedRows === self::BATCH_SIZE);
361 $tableColumns = GeneralUtility::makeInstance(ConnectionPool::class)
362 ->getConnectionForTable($table)
364 ->listTableColumns($table);
365 return isset($tableColumns[$fieldName]);
376 $registry = GeneralUtility::makeInstance(Registry::class);
377 $startPosition = $registry->get(
'installSeparateHistoryFromSysLog',
'phaseAndPosition', []);
378 if (empty($startPosition)) {
383 $registry->set(
'installSeparateHistoryFromSysLog',
'phaseAndPosition', $startPosition);
386 return $startPosition;
391 $unserialized = unserialize($serialized, [
'allowed_classes' =>
false]);
392 return is_array($unserialized) ? $unserialized : [];