From 9c8e1aa982127074c39e1b1d03ccf0b1e5eaee4b Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Mon, 15 May 2023 15:35:48 +0200 Subject: [PATCH] Do not delete files if they are still in use (#12) The clean up task had an issue to clean up to many files. It didn't check if a file that could be deleted because one event got deleted, was still in use by another event. Relates: #10499 --- Classes/Service/Cleanup/Files.php | 45 +++++++++++++------ Documentation/Changelog/3.4.1.rst | 30 +++++++++++++ .../Fixtures/RemovePastTestDatabase.php | 37 +++++++++++++++ ext_emconf.php | 2 +- 4 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 Documentation/Changelog/3.4.1.rst diff --git a/Classes/Service/Cleanup/Files.php b/Classes/Service/Cleanup/Files.php index 4dd7cc4..ee07029 100644 --- a/Classes/Service/Cleanup/Files.php +++ b/Classes/Service/Cleanup/Files.php @@ -112,7 +112,9 @@ class Files { $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file'); $queryBuilder->getRestrictions()->removeAll(); - $queryBuilder->select('file.identifier', 'file.storage', 'file.uid') + $queryBuilder + ->select('file.identifier', 'file.storage', 'file.uid') + ->addSelectLiteral('SUM(' . $queryBuilder->expr()->eq('reference.deleted', 1) . ') AS deleted_sum') ->from('sys_file', 'file') ->leftJoin( 'file', @@ -120,15 +122,18 @@ class Files 'reference', 'reference.uid_local = file.uid' ) - ->where($queryBuilder->expr()->eq( - 'reference.deleted', - 1 - )) - ->andWhere($queryBuilder->expr()->like( + ->where($queryBuilder->expr()->like( 'reference.tablenames', $queryBuilder->createNamedParameter('tx_events_domain_model_%') )) - ; + ->groupBy('file.uid') + ->having( + $queryBuilder->expr()->eq( + 'deleted_sum', + $queryBuilder->expr()->count('*') + ) + ) + ; /** @var array{int: array{storage: int, identifier: string, uid: int}} $filesToDelete */ $filesToDelete = $queryBuilder->execute()->fetchAll(); @@ -160,16 +165,30 @@ class Files ->setParameter(':uids', $uids, Connection::PARAM_INT_ARRAY) ->execute(); - $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file_reference'); - $queryBuilder->delete('sys_file_reference') - ->where('uid_local in (:uids)') - ->setParameter(':uids', $uids, Connection::PARAM_INT_ARRAY) - ->execute(); - $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file_metadata'); $queryBuilder->delete('sys_file_metadata') ->where('file in (:uids)') ->setParameter(':uids', $uids, Connection::PARAM_INT_ARRAY) ->execute(); + + $this->deleteReferences(); + } + + private function deleteReferences(): void + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file'); + $queryBuilder->getRestrictions()->removeAll(); + $queryBuilder + ->delete('sys_file_reference') + ->where($queryBuilder->expr()->like( + 'tablenames', + $queryBuilder->createNamedParameter('tx_events_domain_model_%') + )) + ->andWhere($queryBuilder->expr()->eq( + 'deleted', + 1 + )) + ; + $queryBuilder->execute(); } } diff --git a/Documentation/Changelog/3.4.1.rst b/Documentation/Changelog/3.4.1.rst new file mode 100644 index 0000000..448c27b --- /dev/null +++ b/Documentation/Changelog/3.4.1.rst @@ -0,0 +1,30 @@ +3.4.1 +===== + +Breaking +-------- + +Nothing + +Features +-------- + +Nothing + +Fixes +----- + +* Do not delete files if they are still in use. + The clean up task had an issue to clean up to many files. + It didn't check if a file that could be deleted because one event got deleted, + was still in use by another event. + +Tasks +----- + +Nothing + +Deprecation +----------- + +Nothing diff --git a/Tests/Functional/Cleanup/Fixtures/RemovePastTestDatabase.php b/Tests/Functional/Cleanup/Fixtures/RemovePastTestDatabase.php index 3e440b1..a44c879 100644 --- a/Tests/Functional/Cleanup/Fixtures/RemovePastTestDatabase.php +++ b/Tests/Functional/Cleanup/Fixtures/RemovePastTestDatabase.php @@ -264,6 +264,22 @@ return [ 'sorting_foreign' => '1', 'table_local' => 'sys_file', ], + [ + 'uid' => '5', + 'pid' => '2', + 'tstamp' => '1373537480', + 'crdate' => '1371484347', + 'cruser_id' => '1', + 'deleted' => '0', + 'hidden' => '0', + 'sys_language_uid' => '0', + 'uid_local' => '3', + 'uid_foreign' => '3', + 'tablenames' => 'tx_events_domain_model_event', + 'fieldname' => 'images', + 'sorting_foreign' => '1', + 'table_local' => 'sys_file', + ], ], 'tx_events_domain_model_region' => [ [ @@ -334,6 +350,19 @@ return [ 'images' => '0', 'categories' => '1', ], + [ + 'uid' => '3', + 'pid' => '2', + 'title' => 'Example Event of past', + 'subtitle' => 'This event will be removed, but references same image that should be kept for event 2', + 'global_id' => '5540-34', + 'slug' => '5540-34', + 'organizer' => '0', + 'partner' => '0', + 'region' => '0', + 'images' => '1', + 'categories' => '0', + ], ], 'tx_events_domain_model_date' => [ [ @@ -352,5 +381,13 @@ return [ 'end' => '9999999999', 'canceled' => 'no', ], + [ + 'uid' => '4', + 'pid' => '2', + 'event' => '3', + 'start' => '0', + 'end' => '10', + 'canceled' => 'no', + ], ], ]; diff --git a/ext_emconf.php b/ext_emconf.php index e213833..ad6cf46 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -9,7 +9,7 @@ $EM_CONF['events'] = [ 'state' => 'alpha', 'createDirs' => '', 'clearCacheOnLoad' => 0, - 'version' => '3.4.0', + 'version' => '3.4.1', 'constraints' => [ 'depends' => [ 'typo3' => '10.4.00-11.5.99',