diff --git a/Classes/Command/CleanupCommand.php b/Classes/Command/CleanupCommand.php index 32383dd..53a9ce5 100644 --- a/Classes/Command/CleanupCommand.php +++ b/Classes/Command/CleanupCommand.php @@ -15,8 +15,29 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use WebVision\WvFileCleanup\Domain\Repository\FileRepository; +/** +The symfony commands wv_file_cleanup:cleanup and wv_file_cleanup:emptyrecycler are available. + +Example of using the command controllers from CLI context: +.vendor/bin/typo3 wv_file_cleanup:cleanup --help +.vendor/bin/typo3 wv_file_cleanup:cleanup 1:/ -r --verbose +.vendor/bin/typo3 wv_file_cleanup:cleanup 1:/Redaktion/Bilder/Aktuelles/2016/ -r --verbose --dry-run +.vendor/bin/typo3 wv_file_cleanup:emptyrecycler 1:/ -a 1month --verbose +To only match *.pdf files you can set the fileNameDenyPattern to /^(?!.*\b.pdf\b)/ +.vendor/bin/typo3 wv_file_cleanup:cleanup 1:/ --verbose --dry-run --file-deny-pattern='/^(?!.*\b.pdf\b)/' + +It is recommended to use the commands in a CLI context, but they can also be setup in the scheduler as scheduler tasks. + +Options +You can configure an fileNameDenyPattern that holds a regular expression that is used to check the filename against. If the pattern matches the file is excluded from the cleanup and also not visible in het BE module. +Default value is /index.html/i so all index.html files are excluded and can be adjusted in the extension configuration (see extension manager). +The value can also be overwritten in the command controller (and scheduler task). + */ + /** * Class CleanupCommand + * + * @package WebVision\WvFileCleanup\Command */ class CleanupCommand extends Command { @@ -25,8 +46,9 @@ class CleanupCommand extends Command */ protected FileRepository $fileRepository; - public function injectFileRepository(FileRepository $fileRepository): void + public function __construct(FileRepository $fileRepository) { + parent::__construct(); $this->fileRepository = $fileRepository; } @@ -76,6 +98,10 @@ protected function configure(): void } /** + * @param InputInterface $input + * @param OutputInterface $output + * + * @return int * @throws InsufficientFolderAccessPermissionsException * @throws ResourceDoesNotExistException */ diff --git a/Classes/Command/EmptyRecyclerCommand.php b/Classes/Command/EmptyRecyclerCommand.php index 879712c..3a38777 100644 --- a/Classes/Command/EmptyRecyclerCommand.php +++ b/Classes/Command/EmptyRecyclerCommand.php @@ -21,20 +21,20 @@ class EmptyRecyclerCommand extends Command /** * @var FileRepository */ - protected $fileRepository; + protected FileRepository $fileRepository; /** * @var ResourceFactory */ - protected $resourceFactory; + protected ResourceFactory $resourceFactory; - public function injectFileRepository(FileRepository $fileRepository): void + public function __construct( + FileRepository $fileRepository, + ResourceFactory $resourceFactory + ) { + parent::__construct(); $this->fileRepository = $fileRepository; - } - - public function injectResourceFactory(ResourceFactory $resourceFactory): void - { $this->resourceFactory = $resourceFactory; } @@ -78,6 +78,10 @@ protected function configure(): void } /** + * @param InputInterface $input + * @param OutputInterface $output + * + * @return int * @throws InsufficientFolderAccessPermissionsException */ protected function execute(InputInterface $input, OutputInterface $output): int diff --git a/Classes/Controller/CleanupController.php b/Classes/Controller/CleanupController.php index 7de4986..17801b5 100644 --- a/Classes/Controller/CleanupController.php +++ b/Classes/Controller/CleanupController.php @@ -3,12 +3,16 @@ namespace WebVision\WvFileCleanup\Controller; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Backend\Routing\UriBuilder; +use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Backend\Module\ModuleData; +use TYPO3\CMS\Backend\Routing\UriBuilder as BackendUriBuilder; use TYPO3\CMS\Backend\Template\Components\ButtonBar; +use TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton; use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Information\Typo3Version; @@ -23,9 +27,16 @@ use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Resource\ResourceStorage; +use TYPO3\CMS\Core\Resource\StorageRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\MathUtility; +use TYPO3\CMS\Core\Utility\PathUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; +use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters; +use TYPO3\CMS\Extbase\Mvc\Request; +use TYPO3\CMS\Extbase\Mvc\RequestInterface; +use TYPO3\CMS\Extbase\Utility\DebuggerUtility; +use \TYPO3Fluid\Fluid\View\ViewInterface; use WebVision\WvFileCleanup\Domain\Repository\FileRepository; /** @@ -45,41 +56,65 @@ class CleanupController extends ActionController protected FileRepository $fileRepository; + protected BackendUriBuilder $backendUriBuilder; + + /** + * @var StorageRepository + */ + protected $storageRepository; + protected IconFactory $iconFactory; + protected ?ModuleData $moduleData = null; + + protected string $moduleIdentifier = ''; + public function __construct( FileRepository $fileRepository, PageRenderer $pageRenderer, ModuleTemplateFactory $moduleTemplateFactory, - IconFactory $iconFactory + IconFactory $iconFactory, + StorageRepository $storageRepository, + BackendUriBuilder $backendUriBuilder ) { $this->fileRepository = $fileRepository; $this->pageRenderer = $pageRenderer; $this->moduleTemplateFactory = $moduleTemplateFactory; $this->iconFactory = $iconFactory; + $this->storageRepository = $storageRepository; + $this->backendUriBuilder = $backendUriBuilder; } public function initializeAction(): void { $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $this->moduleData = $this->request->getAttribute('moduleData'); + $this->moduleIdentifier = $this->moduleData->getModuleIdentifier(); } public function initializeView(ViewInterface $view): void { - $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu'); - $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/WvFileCleanup/Cleanup'); - $this->pageRenderer->addJsInlineCode( - 'FileCleanup', - 'function jumpToUrl(URL) { - window.location.href = URL; - return false; - }' - ); + +// $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu'); +// $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/WvFileCleanup/Cleanup'); + // Load JavaScript via PageRenderer + $this->pageRenderer->loadJavaScriptModule('@typo3/backend/context-menu.js'); + $this->pageRenderer->loadJavaScriptModule('@WebVision/WvFileCleanup/Cleanup.js'); +// $this->pageRenderer->addJsInlineCode( +// 'FileCleanup', +// 'function jumpToUrl(URL) { +// window.location.href = URL; +// return false; +// }' +// ); $this->registerDocHeaderButtons(); $pageRecord = [ 'combined_identifier' => $this->folder->getCombinedIdentifier(), ]; + +// $arguments = $this->request->getArguments(); + $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pageRecord); } @@ -96,13 +131,22 @@ public function initializeObject(): void $this->getLanguageService()->includeLLFile('EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf'); // GPvars - $combinedIdentifier = GeneralUtility::_GP('id'); + //$combinedIdentifier = GeneralUtility::_GP('id'); + $this->request = $this->getExtbaseRequest(); + $combinedIdentifier = ($this->request->getParsedBody()['id'] ?? $this->request->getQueryParams()['id'] ?? null); try { if ($combinedIdentifier) { /** @var $resourceFactory ResourceFactory **/ $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); - $storage = $resourceFactory->getStorageObjectFromCombinedIdentifier($combinedIdentifier); + //$storage = $resourceFactory->getStorageObjectFromCombinedIdentifier($combinedIdentifier); + [$storageId, $objectIdentifier] = array_pad(GeneralUtility::trimExplode(':', $combinedIdentifier), 2, null); + if (!MathUtility::canBeInterpretedAsInteger($storageId) && $objectIdentifier === null) { + $storage = $this->storageRepository->getDefaultStorage(); + } else { + $storage = $this->storageRepository->findByUid((int)$storageId); + } + $identifier = substr($combinedIdentifier, strpos($combinedIdentifier, ':') + 1); if (!$storage->hasFolder($identifier)) { $identifier = $storage->getFolderIdentifierFromFileIdentifier($identifier); @@ -140,11 +184,11 @@ public function initializeObject(): void $this->folder = null; $this->addFlashMessage( sprintf( - $this->getLanguageService()->getLL('missingFolderPermissionsMessage'), + $this->getLanguageService()->sL('missingFolderPermissionsMessage'), htmlspecialchars($combinedIdentifier) ), - $this->getLanguageService()->getLL('missingFolderPermissionsTitle'), - FlashMessage::NOTICE + $this->getLanguageService()->sL('missingFolderPermissionsTitle'), + \TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::NOTICE ); } catch (Exception $fileException) { // Set folder object to null and throw a message later on @@ -160,18 +204,18 @@ public function initializeObject(): void } $this->addFlashMessage( sprintf( - $this->getLanguageService()->getLL('folderNotFoundMessage'), + $this->getLanguageService()->sL('folderNotFoundMessage'), htmlspecialchars($combinedIdentifier) ), - $this->getLanguageService()->getLL('folderNotFoundTitle'), - FlashMessage::NOTICE + $this->getLanguageService()->sL('folderNotFoundTitle'), + \TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::NOTICE ); } catch (\RuntimeException $e) { $this->folder = null; $this->addFlashMessage( $e->getMessage() . ' (' . $e->getCode() . ')', - $this->getLanguageService()->getLL('folderNotFoundTitle'), - FlashMessage::NOTICE + $this->getLanguageService()->sL('folderNotFoundTitle'), + \TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::NOTICE ); } @@ -190,14 +234,17 @@ public function initializeObject(): void */ protected function optionsConfig(): void { + $this->moduleSettings = BackendUtility::getModuleData( [ 'displayThumbs' => '', 'recursive' => '', ], - GeneralUtility::_GP('SET'), + //GeneralUtility::_GP('SET'), + $this->request->getQueryParams()['SET'] ?? null, 'file_WvFileCleanupCleanup' ); + } /** @@ -226,17 +273,24 @@ protected function initializeIndexAction(): void protected function registerDocHeaderButtons(): void { $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); - // Refresh page - $refreshLink = GeneralUtility::linkThisScript( +// $refreshLink = GeneralUtility::linkThisScript( +// [ +// 'target' => rawurlencode($this->folder->getCombinedIdentifier()), +// ] +// ); + + $refreshLink = $this->backendUriBuilder->buildUriFromRoute( + $this->moduleIdentifier, [ 'target' => rawurlencode($this->folder->getCombinedIdentifier()), ] ); + $buttonFactory = GeneralUtility::makeInstance( - \TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton::class + LinkButton::class ); - $buttonTitle = $this->getLanguageService()->getLL('labels.reload'); + $buttonTitle = $this->getLanguageService()->sL('labels.reload'); $refreshButton = $buttonBar->makeLinkButton($buttonFactory) ->setHref($refreshLink) ->setTitle($buttonTitle) @@ -252,15 +306,14 @@ protected function registerDocHeaderButtons(): void $parentFolder->getIdentifier() !== $this->folder->getIdentifier() && $currentStorage->isWithinFileMountBoundaries($parentFolder) ) { - $levelUpTitle = $this->getLanguageService()->getLL('labels.upOneLevel'); + $levelUpTitle = $this->getLanguageService()->sL('labels.upOneLevel'); if (!$levelUpTitle) { $levelUpTitle = 'Up one level'; } - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); $levelUpButton = $buttonBar->makeLinkButton($buttonFactory) ->setHref( - (string)$uriBuilder->buildUriFromRoute( - 'file_WvFileCleanupCleanup', + (string)$this->backendUriBuilder->buildUriFromRoute( + $this->moduleIdentifier, ['id' => $parentFolder->getCombinedIdentifier()] ) ) @@ -282,7 +335,7 @@ protected function registerDocHeaderButtons(): void // Shortcut if ($this->getBackendUser()->mayMakeShortcut()) { $shortCutButton = $buttonBar->makeShortcutButton() - ->setRouteIdentifier('file_WvFileCleanupCleanup') + ->setRouteIdentifier($this->moduleIdentifier) ->setDisplayName('File cleanup'); $buttonBar->addButton($shortCutButton, ButtonBar::BUTTON_POSITION_RIGHT); } @@ -293,47 +346,71 @@ protected function registerDocHeaderButtons(): void */ public function indexAction(): ResponseInterface { - $this->view->assign('files', $this->fileRepository->findUnusedFile($this->folder, $this->moduleSettings['recursive'] ?? false)); - $this->view->assign('folder', $this->folder); + $this->moduleTemplate->assign('files', $this->fileRepository->findUnusedFile($this->folder, $this->moduleSettings['recursive'] ?? false)); + $this->moduleTemplate->assign('folder', $this->folder); $backendUserTsconfig = $this->getBackendUserTsconfig(); - $this->view->assign('checkboxes', [ + + $attributesDisplayThumbs = GeneralUtility::implodeAttributes([ + 'type' => 'checkbox', + 'class' => 'checkbox', + 'name' => 'SET[displayThumbs]', + 'value' => '1', + 'data-global-event' => 'change', + 'data-action-navigate' => '$data=~s/$value/', + 'data-navigate-value' => sprintf( + '%s&%s=${value}', + (string)$this->backendUriBuilder->buildUriFromRoute( + $this->moduleIdentifier, + ['id' =>$this->folder ? $this->folder->getCombinedIdentifier() : ''] + ), + 'SET[displayThumbs]' + ), + 'data-empty-value' => '0', + ], true); + $attributesRecursive = GeneralUtility::implodeAttributes([ + 'type' => 'checkbox', + 'class' => 'checkbox', + 'name' => 'SET[recursive]', + 'value' => '1', + 'data-global-event' => 'change', + 'data-action-navigate' => '$data=~s/$value/', + 'data-navigate-value' => sprintf( + '%s&%s=${value}', + (string)$this->backendUriBuilder->buildUriFromRoute( + $this->moduleIdentifier, + ['id' =>$this->folder ? $this->folder->getCombinedIdentifier() : ''] + ), + 'SET[recursive]' + ), + 'data-empty-value' => '0', + ], true); + + $this->moduleTemplate->assign('checkboxes', [ 'displayThumbs' => [ 'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $backendUserTsconfig['options.']['file_list.']['enableDisplayThumbnails'] === 'selectable', - 'label' => $this->getLanguageService()->getLL('displayThumbs'), - 'html' => BackendUtility::getFuncCheck( - $this->folder ? $this->folder->getCombinedIdentifier() : '', - 'SET[displayThumbs]', - $this->moduleSettings['displayThumbs'], - '', - '', - 'id="checkDisplayThumbs"' - ), + 'label' => $this->getLanguageService()->sL('LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:displayThumbs'), + 'html' => 'moduleSettings['displayThumbs']) ? ' checked="checked"' : '') . 'id="checkDisplayThumbs" />', 'checked' => $this->moduleSettings['displayThumbs'], ], 'recursive' => [ 'enabled' => true, - 'label' => $this->getLanguageService()->getLL('search_folders_recursive'), - 'html' => BackendUtility::getFuncCheck( - $this->folder ? $this->folder->getCombinedIdentifier() : '', - 'SET[recursive]', - $this->moduleSettings['recursive'] ?? false, - '', - '', - 'id="checkRecursive"' - ), + 'label' => $this->getLanguageService()->sL('LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:search_folders_recursive'), + 'html' => 'moduleSettings['recursive']) ? ' checked="checked"' : '') . 'id="checkRecursive" />', 'checked' => $this->moduleSettings['recursive'] ?? false, ], ]); - $this->moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($this->moduleTemplate->renderContent()); + + return $this->moduleTemplate->renderResponse('Cleanup/Index'); } /** * Cleanup files * * @param array $files + * + * @return ResponseInterface * @throws ExistingTargetFolderException * @throws InsufficientFolderAccessPermissionsException * @throws \TYPO3\CMS\Core\Exception @@ -359,7 +436,7 @@ public function cleanupAction(array $files): ResponseInterface $this->addFlashMessage( 'You are not allowed to create a _recycler_ folder in ' . $folder->getReadablePath(), '', - FlashMessage::ERROR, + \TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::ERROR, true ); } @@ -376,7 +453,7 @@ public function cleanupAction(array $files): ResponseInterface $this->addFlashMessage( 'No files moved', '', - FlashMessage::WARNING, + \TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::WARNING, true ); } @@ -398,7 +475,7 @@ public function cleanupAction(array $files): ResponseInterface public function addFlashMessage( $messageBody, $messageTitle = '', - $severity = \TYPO3\CMS\Core\Messaging\AbstractMessage::OK, + $severity = \TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::OK, $storeInSession = true ): void { if (!is_string($messageBody)) { @@ -435,4 +512,15 @@ protected function getBackendUserTsconfig(): array { return $this->getBackendUser()->getTSConfig(); } + + private function getExtbaseRequest(): RequestInterface + { + /** @var ServerRequestInterface $request */ + $request = $GLOBALS['TYPO3_REQUEST']; + + // We have to provide an Extbase request object + return new Request( + $request->withAttribute('extbase', new ExtbaseRequestParameters()), + ); + } } diff --git a/Classes/Domain/Repository/FileRepository.php b/Classes/Domain/Repository/FileRepository.php index 9d65d96..0e203a7 100644 --- a/Classes/Domain/Repository/FileRepository.php +++ b/Classes/Domain/Repository/FileRepository.php @@ -14,6 +14,7 @@ use TYPO3\CMS\Core\Resource\ProcessedFile; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Utility\DebuggerUtility; use WebVision\WvFileCleanup\FileFacade; use WebVision\WvFileCleanup\Service\FileCollectionService; @@ -59,6 +60,11 @@ public function __construct() /** * Find all unused files * + * @param Folder $folder + * @param bool $recursive + * @param string|null $fileDenyPattern + * @param string|null $pathDenyPattern + * * @return FileFacade[] * @throws ResourceDoesNotExistException */ @@ -72,6 +78,7 @@ public function findUnusedFile( $return = []; $files = $folder->getFiles(0, 0, Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive); + if ($fileDenyPattern === null) { $fileDenyPattern = $this->fileNameDenyPattern; } @@ -115,7 +122,7 @@ public function findUnusedFile( * * @param Folder $folder * @param bool $recursive - * @param string $fileDenyPattern + * @param string|null $fileDenyPattern * * @return File[] */ @@ -180,7 +187,7 @@ public function getReferenceCount(File $file): int $queryBuilder1->createNamedParameter('sys_file_metadata', Connection::PARAM_STR) ) ) - ->execute(); + ->executeQuery(); $refIndexCount = (int)$res1->fetchOne(); // sys_file_reference @@ -194,7 +201,7 @@ public function getReferenceCount(File $file): int $queryBuilder2->createNamedParameter($file->getUid(), Connection::PARAM_INT) ), ) - ->execute(); + ->executeQuery(); $fileReferenceCount = (int)$res2->fetchOne(); return max($refIndexCount, $fileReferenceCount); @@ -209,8 +216,8 @@ public function getLastMove(File $file): int ->where( $queryBuilder->expr()->eq('uid', (int)$file->getUid()) ) - ->execute(); - $row = $res->fetch(); + ->executeQuery(); + $row = $res->fetchAssociative(); return $row ? $row['last_move'] : 0; } diff --git a/Classes/FileFacade.php b/Classes/FileFacade.php index 94935f4..123e846 100644 --- a/Classes/FileFacade.php +++ b/Classes/FileFacade.php @@ -16,8 +16,12 @@ */ use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -38,12 +42,12 @@ class FileFacade protected static $lastReferenceTimestamps = []; /** - * @var \TYPO3\CMS\Core\Resource\FileInterface + * @var FileInterface */ protected $resource; /** - * @var \TYPO3\CMS\Core\Database\ConnectionPool + * @var ConnectionPool */ protected $queryBuilder; @@ -54,9 +58,9 @@ class FileFacade protected $databaseConnection; /** - * @param \TYPO3\CMS\Core\Resource\FileInterface $resource + * @param FileInterface $resource */ - public function __construct(\TYPO3\CMS\Core\Resource\FileInterface $resource) + public function __construct(FileInterface $resource) { $this->resource = $resource; $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); @@ -68,11 +72,11 @@ public function __construct(\TYPO3\CMS\Core\Resource\FileInterface $resource) public function getIcon() { $title = htmlspecialchars($this->resource->getName() . ' [' . (int)$this->resource->getProperty('uid') . ']'); - return '' . $this->iconFactory->getIconForResource($this->resource, Icon::SIZE_SMALL) . ''; + return '' . $this->iconFactory->getIconForResource($this->resource, \TYPO3\CMS\Core\Imaging\Icon::SIZE_SMALL) . ''; } /** - * @return \TYPO3\CMS\Core\Resource\FileInterface + * @return FileInterface */ public function getResource() { @@ -164,7 +168,7 @@ public function getLastModified() */ public function getSize() { - return GeneralUtility::formatSize($this->resource->getSize(), $this->getLanguageService()->getLL('byteSizeUnits')); + return GeneralUtility::formatSize($this->resource->getSize(), $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:byteSizeUnits')); } /** @@ -267,7 +271,7 @@ public function getLastReferenceTimestamp() $queryBuilder->expr()->eq('deleted', 1) ) ->orderBy('tstamp DESC') - ->execute(); + ->executeQuery(); $row = $result->fetchAllAssociative(); } @@ -296,11 +300,11 @@ public function __call($method, $arguments) protected function initDatabaseConnection() { - $this->queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class); + $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class); } /** - * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication + * @return BackendUserAuthentication */ protected function getBackendUser() { @@ -308,7 +312,7 @@ protected function getBackendUser() } /** - * @return \TYPO3\CMS\Core\Localization\LanguageService + * @return LanguageService */ protected function getLanguageService() { diff --git a/Classes/Listener/ResourceStorageListener.php b/Classes/Listener/ResourceStorageListener.php index 6791a5f..c597882 100644 --- a/Classes/Listener/ResourceStorageListener.php +++ b/Classes/Listener/ResourceStorageListener.php @@ -21,7 +21,7 @@ public function postFileMove(AfterFileMovedEvent $event): void $queryBuilder->expr()->eq('uid', (int)$file->getUid()) ) ->set('last_move', time()) - ->execute(); + ->executeStatement(); } } } diff --git a/Classes/Service/FileCollectionService.php b/Classes/Service/FileCollectionService.php index 86ba5f7..d8b3c56 100644 --- a/Classes/Service/FileCollectionService.php +++ b/Classes/Service/FileCollectionService.php @@ -100,8 +100,8 @@ private function getFileCollectionUidsForCategoryCollections(): array $queryBuilder->createNamedParameter('category', Connection::PARAM_STR) ) ) - ->execute() - ->fetchAll(); + ->executeQuery() + ->fetchAllAssociative(); $result = []; foreach ($queryResult as $record) { @@ -138,8 +138,8 @@ private function getFilesLTS12($storage, $folder): array ) ) ) - ->execute() - ->fetchAll(); + ->executeQuery() + ->fetchAllAssociative(); return $queryResult; } @@ -174,8 +174,8 @@ private function getFilesLTS11($storage, $folder): array ) ) ) - ->execute() - ->fetchAll(); + ->executeQuery() + ->fetchAllAssociative(); return $queryResult; } } diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php new file mode 100644 index 0000000..c9d0e68 --- /dev/null +++ b/Configuration/JavaScriptModules.php @@ -0,0 +1,19 @@ + [ + 'backend', + 'core', + ], + 'tags' => [ + 'backend.module', + ], + 'imports' => [ + // recursive definition, all *.js files in this folder are import-mapped + // trailing slash is required per importmap-specification + '@typo3/backend/' => 'EXT:backend/Resources/Public/JavaScript/', + '@WebVision/WvFileCleanup/' => 'EXT:wv_file_cleanup/Resources/Public/JavaScript/', + ] +]; diff --git a/Resources/Private/Language/locallang_mod_cleanup.xlf b/Resources/Private/Language/locallang_mod_cleanup.xlf index 69218c1..124e2e8 100644 --- a/Resources/Private/Language/locallang_mod_cleanup.xlf +++ b/Resources/Private/Language/locallang_mod_cleanup.xlf @@ -19,6 +19,9 @@ Cleanup selected files + + Display thumbnails + No files found @@ -31,7 +34,18 @@ excluded from cleanup. - + + Path + + + Date + + + Settings + + + Folder + diff --git a/Resources/Private/Templates/Cleanup/Index.html b/Resources/Private/Templates/Cleanup/Index.html index bc1dbb3..ba532ea 100644 --- a/Resources/Private/Templates/Cleanup/Index.html +++ b/Resources/Private/Templates/Cleanup/Index.html @@ -2,94 +2,99 @@ xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" xmlns:fl="http://typo3.org/ns/WebVision/WvFileCleanup/ViewHelpers"> - + - -

{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:mlang_tabs_tab')}

-
+ + + - - +

{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:mlang_tabs_tab')}

+

{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:folder')}: {folder.identifier}

+ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_filepath' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_file' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_fileext' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_tstamp' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_size' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_rw' )}{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:last_know_usage' )}
- - - - - - {file.icon->f:format.raw()} - - - - - {file.icon->f:format.raw()} - - - - - {file.path} - - {file.name->f:format.crop( maxCharacters:30 )} - - -
- -
-
-
{file.extension}{file.lastModified}{file.size} - {f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:read' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:write' )} - - - - {file.lastReferenceTimestamp} - - - - - - -
-
- - - + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + {f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_name' )}{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:filepath' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_record_type' )}{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:tstamp' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_size' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_rw' )}{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:last_know_usage' )}
+ + + + + + {file.icon->f:format.raw()} + + + + + {file.icon->f:format.raw()} + + + + + {file.name->f:format.crop( maxCharacters:30 )} + + +
+ +
+
+
+ {file.path} + {file.extension}{file.lastModified}{file.size} + {f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:read' )}{f:translate( key:'LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:write' )} + + + + {file.lastReferenceTimestamp} + + + - + + +
+
-
+

{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:no_files_found' )}

-
+
@@ -107,7 +112,8 @@

{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locall - +

{f:translate( key:'LLL:EXT:wv_file_cleanup/Resources/Private/Language/locallang_mod_cleanup.xlf:settings')}

+
-
- \ No newline at end of file + diff --git a/Resources/Public/JavaScript/Cleanup.js b/Resources/Public/JavaScript/Cleanup.js index bab8f4f..e57f25d 100644 --- a/Resources/Public/JavaScript/Cleanup.js +++ b/Resources/Public/JavaScript/Cleanup.js @@ -12,17 +12,22 @@ */ /** - * Module: WebVision/WvFileCleanup/Cleanup - * @exports WebVision/WvFileCleanup/Cleanup + * Module: @WebVision/WvFileCleanup/Cleanup.js */ -define(['jquery'], function($) { - $('.js-cleanup-all').on('click', function(){ +import $ from 'jquery'; + + +function selectAll() { + $('.js-cleanup-all').on('click', function () { if ($(this).is(':checked')) { - $('.js-cleanup-checkbox').attr('checked', true); + $('.js-cleanup-checkbox').prop('checked', true); } else { - $('.js-cleanup-checkbox').attr('checked', false); + $('.js-cleanup-checkbox').prop('checked', false); } }); +} -}); \ No newline at end of file +$(document).ready(function () { + selectAll(); +}); diff --git a/composer.json b/composer.json index 245764a..ffe1b32 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "license": ["GPL-3.0+"], "require": { "php": ">=7.4 || >= 8.0", - "typo3/cms-core": "^11.5 || ^12.4" + "typo3/cms-core": "^12.4 || ^13.4" }, "require-dev": { "typo3/testing-framework": "^6.16 || ^7.0",