diff --git a/.github/workflows/phpci.yml b/.github/workflows/phpci.yml index cc07ae9..1ca1536 100644 --- a/.github/workflows/phpci.yml +++ b/.github/workflows/phpci.yml @@ -66,6 +66,7 @@ jobs: matrix: command: - "test:phpcs" + - "test:rector", - "test:phpcompatibility" - "test:phpmd" - "test:phpstan" diff --git a/Classes/Cleaner/AbstractCommandCleaner.php b/Classes/Cleaner/AbstractCommandCleaner.php index 046a296..916c2be 100644 --- a/Classes/Cleaner/AbstractCommandCleaner.php +++ b/Classes/Cleaner/AbstractCommandCleaner.php @@ -52,19 +52,21 @@ abstract class AbstractCommandCleaner implements SingletonInterface, CleanerInte */ public function __construct() { - $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); + $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(self::class); } protected function executeCommand(string $command, string $parameters): bool { $command = CommandUtility::getCommand($command).' '.$parameters; - $output = $returnValue = ''; + $output = null; + $returnValue = 0; CommandUtility::exec($command, $output, $returnValue); if ($returnValue) { $this->logger->warning('exec', ['cmd' => $command, 'output' => $output, 'returnValue' => $returnValue]); return false; } + $this->logger->info('exec', ['cmd' => $command, 'output' => $output, 'returnValue' => $returnValue]); return true; diff --git a/Classes/Cleaner/Registry.php b/Classes/Cleaner/Registry.php index 3e36a7b..cade26c 100644 --- a/Classes/Cleaner/Registry.php +++ b/Classes/Cleaner/Registry.php @@ -43,10 +43,7 @@ class Registry */ protected static $registeredCleaners = []; - /** - * @return void - */ - public static function registerCleaner(string $className, int $priority) + public static function registerCleaner(string $className, int $priority): void { if (isset(self::$registeredCleaners[$priority])) { throw new \Exception('Priority '.$priority.' for cleaner '.$className.' already in use'); @@ -62,10 +59,7 @@ public static function registerCleaner(string $className, int $priority) asort(self::$registeredCleaners); } - /** - * @return void - */ - public static function unregisterCleaner(string $className) + public static function unregisterCleaner(string $className): void { foreach (self::$registeredCleaners as $priority => $cleaner) { if ($cleaner instanceof $className) { diff --git a/Classes/Command/CleanerCommand.php b/Classes/Command/CleanerCommand.php index 6ecc5fe..295a4d5 100644 --- a/Classes/Command/CleanerCommand.php +++ b/Classes/Command/CleanerCommand.php @@ -45,7 +45,7 @@ class CleanerCommand extends Command { public function __construct( protected CleanerService $cleanerService, - protected Helper $taskHelper + protected Helper $taskHelper, ) { parent::__construct(); } diff --git a/Classes/EventListener/UploadedFileEventListener.php b/Classes/EventListener/UploadedFileEventListener.php index 95ad1eb..f174989 100644 --- a/Classes/EventListener/UploadedFileEventListener.php +++ b/Classes/EventListener/UploadedFileEventListener.php @@ -29,7 +29,6 @@ use DMK\Mkcleaner\Service\CleanerService; use TYPO3\CMS\Core\Resource\Event\AfterFileAddedEvent; -use TYPO3\CMS\Core\Utility\GeneralUtility; /*************************************************************** * Copyright notice @@ -55,16 +54,21 @@ ***************************************************************/ /** - * MKKVS hook for uploaded file (create/delete). + * Class UploadedFileEventListener. * - * @author Markus Crasser + * @author Hannes Bochmann * @license http://www.gnu.org/licenses/lgpl.html * GNU Lesser General Public License, version 3 or later */ class UploadedFileEventListener { - public function cleanUp(AfterFileAddedEvent $event): void + public function __construct( + protected CleanerService $cleanerService, + ) { + } + + public function cleanUpFile(AfterFileAddedEvent $event): void { - GeneralUtility::makeInstance(CleanerService::class)->cleanupFile($event->getFile()); + $this->cleanerService->cleanupFile($event->getFile()); } } diff --git a/Classes/Service/CleanerService.php b/Classes/Service/CleanerService.php index c0e60c8..abc6930 100644 --- a/Classes/Service/CleanerService.php +++ b/Classes/Service/CleanerService.php @@ -33,7 +33,7 @@ use TYPO3\CMS\Core\SingletonInterface; /** - * Class Mat2Service. + * Class CleanerService. * * @author Hannes Bochmann * @license http://www.gnu.org/licenses/lgpl.html @@ -41,20 +41,14 @@ */ class CleanerService implements SingletonInterface { - /** - * @return void - */ - public function cleanupFolder(Folder $folder) + public function cleanupFolder(Folder $folder): void { foreach ($folder->getFiles(0, 0, Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, true) as $file) { $this->cleanupFile($file); } } - /** - * @return void - */ - public function cleanupFile(FileInterface $file) + public function cleanupFile(FileInterface $file): void { foreach (Registry::getRegisteredCleaners() as $cleaner) { if ($cleaner->canHandleFile($file)) { diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 393706e..1b93534 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -8,7 +8,7 @@ services: tags: - name: event.listener identifier: 'UploadedFileEventListener' - method: 'cleanUp' + method: 'cleanUpFile' event: TYPO3\CMS\Core\Resource\Event\AfterFileAddedEvent DMK\Mkcleaner\Command\CleanerCommand: diff --git a/Tests/CleanerTestCase.php b/Tests/CleanerTestCase.php new file mode 100644 index 0000000..617abdc --- /dev/null +++ b/Tests/CleanerTestCase.php @@ -0,0 +1,73 @@ + + * All rights reserved + * + * This file is part of the "mkcleaner" Extension for TYPO3 CMS. + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNU Lesser General Public License can be found at + * www.gnu.org/licenses/lgpl.html + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +namespace DMK\Mkcleaner\Tests; + +use DMK\Mkcleaner\Cleaner\AbstractCommandCleaner; +use TYPO3\CMS\Core\Log\Logger; +use TYPO3\CMS\Core\Log\LogManager; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; + +/** + * Class CleanerTestCase. + * + * @author Hannes Bochmann + * @license http://www.gnu.org/licenses/lgpl.html + * GNU Lesser General Public License, version 3 or later + */ +abstract class CleanerTestCase extends UnitTestCase +{ + protected bool $resetSingletonInstances = true; + + protected Logger $logger; + + protected string $fixturesFolder; + + protected function setUp(): void + { + parent::setUp(); + + $this->logger = $this->getMockBuilder(Logger::class) + ->disableOriginalConstructor() + ->getMock(); + $logManager = $this->getMockBuilder(LogManager::class) + ->disableOriginalConstructor() + ->getMock(); + $logManager + ->expects(self::once()) + ->method('getLogger') + ->with(AbstractCommandCleaner::class) + ->willReturn($this->logger); + GeneralUtility::setSingletonInstance(LogManager::class, $logManager); + $this->fixturesFolder = realpath(__DIR__.'/Fixtures'); + $GLOBALS['TYPO3_CONF_VARS']['SYS']['binPath'] = ''; + $GLOBALS['TYPO3_CONF_VARS']['BE']['disable_exec_function'] = false; + $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'] = ''; + defined('LF') ?: define('LF', chr(10)); + } +} diff --git a/Tests/Unit/Cleaner/ExiftoolAndQpdfCleanerTest.php b/Tests/Unit/Cleaner/ExiftoolAndQpdfCleanerTest.php index a7e5752..e07b5cc 100644 --- a/Tests/Unit/Cleaner/ExiftoolAndQpdfCleanerTest.php +++ b/Tests/Unit/Cleaner/ExiftoolAndQpdfCleanerTest.php @@ -27,13 +27,9 @@ namespace DMK\Mkcleaner\Tests\Cleaner; -use DMK\Mkcleaner\Cleaner\AbstractCommandCleaner; use DMK\Mkcleaner\Cleaner\ExiftoolAndQpdfCleaner; -use Nimut\TestingFramework\TestCase\UnitTestCase; -use TYPO3\CMS\Core\Log\Logger; -use TYPO3\CMS\Core\Log\LogManager; +use DMK\Mkcleaner\Tests\CleanerTestCase; use TYPO3\CMS\Core\Resource\File; -use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Class ExiftoolAndQpdfCleanerTest. @@ -42,66 +38,40 @@ * @license http://www.gnu.org/licenses/lgpl.html * GNU Lesser General Public License, version 3 or later */ -class ExiftoolAndQpdfCleanerTest extends UnitTestCase +class ExiftoolAndQpdfCleanerTest extends CleanerTestCase { - /** - * @var Logger - */ - protected $logger; - - /** - * @var ExiftoolAndQpdfCleaner - */ - protected $exiftoolAndQpdfCleaner; + protected ExiftoolAndQpdfCleaner $exiftoolAndQpdfCleaner; - /** - * @var string - */ - protected $fixturesFolder; - - protected function setUp() + protected function setUp(): void { parent::setUp(); - - $this->logger = $this->getMockBuilder(Logger::class) - ->disableOriginalConstructor() - ->getMock(); - $logManager = $this->getMockBuilder(LogManager::class) - ->disableOriginalConstructor() - ->getMock(); - $logManager - ->expects(self::once()) - ->method('getLogger') - ->with(AbstractCommandCleaner::class) - ->willReturn($this->logger); - GeneralUtility::setSingletonInstance(LogManager::class, $logManager); $this->exiftoolAndQpdfCleaner = new ExiftoolAndQpdfCleaner(); - - $this->fixturesFolder = realpath(dirname(__FILE__).'/../../Fixtures'); $GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup'] = 'mat2='.$this->fixturesFolder.'/mat2,'. 'exiftool='.$this->fixturesFolder.'/exiftool,'. 'qpdf='.$this->fixturesFolder.'/qpdf'; } - protected function tearDown() + protected function tearDown(): void { - parent::tearDown(); - if (file_exists($this->fixturesFolder.'/exiftool_failure')) { unlink($this->fixturesFolder.'/exiftool_failure'); } + if (file_exists($this->fixturesFolder.'/qpdf_failure')) { unlink($this->fixturesFolder.'/qpdf_failure'); } + if (file_exists($this->fixturesFolder.'/testPath_intermediate')) { unlink($this->fixturesFolder.'/testPath_intermediate'); } + + parent::tearDown(); } /** * @test */ - public function cleanupFile() + public function cleanupFile(): void { touch($this->fixturesFolder.'/testPath_intermediate'); $file = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); @@ -120,7 +90,7 @@ public function cleanupFile() [ 'exec', [ - 'cmd' => $this->fixturesFolder.'/exiftool -all:all= \''.$this->fixturesFolder.'/testPath\' -o \''.$this->fixturesFolder.'/testPath_intermediate\'', + 'cmd' => $this->fixturesFolder."/exiftool -all:all= '".$this->fixturesFolder."/testPath' -o '".$this->fixturesFolder."/testPath_intermediate'", 'output' => ['exiftool executed'], 'returnValue' => 0, ], @@ -128,20 +98,20 @@ public function cleanupFile() [ 'exec', [ - 'cmd' => $this->fixturesFolder.'/qpdf --linearize \''.$this->fixturesFolder.'/testPath_intermediate\' \''.$this->fixturesFolder.'/testPath\'', + 'cmd' => $this->fixturesFolder."/qpdf --linearize '".$this->fixturesFolder."/testPath_intermediate' '".$this->fixturesFolder."/testPath'", 'output' => ['qpdf executed'], 'returnValue' => 0, ], ] ); self::assertTrue($this->exiftoolAndQpdfCleaner->cleanupFile($file)); - self::assertFileNotExists($this->fixturesFolder.'/testPath_intermediate'); + self::assertFileDoesNotExist($this->fixturesFolder.'/testPath_intermediate'); } /** * @test */ - public function cleanupFileIfExiftoolFails() + public function cleanupFileIfExiftoolFails(): void { touch($this->fixturesFolder.'/testPath_intermediate'); touch($this->fixturesFolder.'/exiftool_failure'); @@ -160,7 +130,7 @@ public function cleanupFileIfExiftoolFails() ->with( 'exec', [ - 'cmd' => $this->fixturesFolder.'/exiftool -all:all= \''.$this->fixturesFolder.'/testPath\' -o \''.$this->fixturesFolder.'/testPath_intermediate\'', + 'cmd' => $this->fixturesFolder."/exiftool -all:all= '".$this->fixturesFolder."/testPath' -o '".$this->fixturesFolder."/testPath_intermediate'", 'output' => ['exiftool executed'], 'returnValue' => 123, ] @@ -172,7 +142,7 @@ public function cleanupFileIfExiftoolFails() /** * @test */ - public function cleanupFileIfIntermediateFileNotCreated() + public function cleanupFileIfIntermediateFileNotCreated(): void { $file = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); $file @@ -189,19 +159,19 @@ public function cleanupFileIfIntermediateFileNotCreated() ->with( 'exec', [ - 'cmd' => $this->fixturesFolder.'/exiftool -all:all= \''.$this->fixturesFolder.'/testPath\' -o \''.$this->fixturesFolder.'/testPath_intermediate\'', + 'cmd' => $this->fixturesFolder."/exiftool -all:all= '".$this->fixturesFolder."/testPath' -o '".$this->fixturesFolder."/testPath_intermediate'", 'output' => ['exiftool executed'], 'returnValue' => 0, ] ); self::assertFalse($this->exiftoolAndQpdfCleaner->cleanupFile($file)); - self::assertFileNotExists($this->fixturesFolder.'/testPath_intermediate'); + self::assertFileDoesNotExist($this->fixturesFolder.'/testPath_intermediate'); } /** * @test */ - public function cleanupFileIfQpdfFails() + public function cleanupFileIfQpdfFails(): void { touch($this->fixturesFolder.'/testPath_intermediate'); touch($this->fixturesFolder.'/qpdf_failure'); @@ -217,7 +187,7 @@ public function cleanupFileIfQpdfFails() ->with( 'exec', [ - 'cmd' => $this->fixturesFolder.'/exiftool -all:all= \''.$this->fixturesFolder.'/testPath\' -o \''.$this->fixturesFolder.'/testPath_intermediate\'', + 'cmd' => $this->fixturesFolder."/exiftool -all:all= '".$this->fixturesFolder."/testPath' -o '".$this->fixturesFolder."/testPath_intermediate'", 'output' => ['exiftool executed'], 'returnValue' => 0, ] @@ -228,14 +198,14 @@ public function cleanupFileIfQpdfFails() ->with( 'exec', [ - 'cmd' => $this->fixturesFolder.'/qpdf --linearize \''.$this->fixturesFolder.'/testPath_intermediate\' \''.$this->fixturesFolder.'/testPath\'', + 'cmd' => $this->fixturesFolder."/qpdf --linearize '".$this->fixturesFolder."/testPath_intermediate' '".$this->fixturesFolder."/testPath'", 'output' => ['qpdf executed'], 'returnValue' => 123, ] ); self::assertFalse($this->exiftoolAndQpdfCleaner->cleanupFile($file)); - self::assertFileNotExists($this->fixturesFolder.'/testPath_intermediate'); + self::assertFileDoesNotExist($this->fixturesFolder.'/testPath_intermediate'); } /** @@ -243,7 +213,7 @@ public function cleanupFileIfQpdfFails() * * @dataProvider canHandleFileDataProvider */ - public function canHandleFileIfSvgFileGiven(string $mimeType, bool $canHandle) + public function canHandleFileIfSvgFileGiven(string $mimeType, bool $canHandle): void { $file = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); $file diff --git a/Tests/Unit/Cleaner/Mat2CleanerTest.php b/Tests/Unit/Cleaner/Mat2CleanerTest.php index 29fba62..4edc7d8 100644 --- a/Tests/Unit/Cleaner/Mat2CleanerTest.php +++ b/Tests/Unit/Cleaner/Mat2CleanerTest.php @@ -27,13 +27,9 @@ namespace DMK\Mkcleaner\Tests\Cleaner; -use DMK\Mkcleaner\Cleaner\AbstractCommandCleaner; use DMK\Mkcleaner\Cleaner\Mat2Cleaner; -use Nimut\TestingFramework\TestCase\UnitTestCase; -use TYPO3\CMS\Core\Log\Logger; -use TYPO3\CMS\Core\Log\LogManager; +use DMK\Mkcleaner\Tests\CleanerTestCase; use TYPO3\CMS\Core\Resource\File; -use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Class Mat2CleanerTest. @@ -42,57 +38,30 @@ * @license http://www.gnu.org/licenses/lgpl.html * GNU Lesser General Public License, version 3 or later */ -class Mat2CleanerTest extends UnitTestCase +class Mat2CleanerTest extends CleanerTestCase { - /** - * @var Logger - */ - protected $logger; - - /** - * @var Mat2Cleaner - */ - protected $mat2Cleaner; - - /** - * @var string - */ - protected $fixturesFolder; + protected Mat2Cleaner $mat2Cleaner; - protected function setUp() + protected function setUp(): void { parent::setUp(); - - $this->logger = $this->getMockBuilder(Logger::class) - ->disableOriginalConstructor() - ->getMock(); - $logManager = $this->getMockBuilder(LogManager::class) - ->disableOriginalConstructor() - ->getMock(); - $logManager - ->expects(self::once()) - ->method('getLogger') - ->with(AbstractCommandCleaner::class) - ->willReturn($this->logger); - GeneralUtility::setSingletonInstance(LogManager::class, $logManager); $this->mat2Cleaner = new Mat2Cleaner(); - $this->fixturesFolder = realpath(dirname(__FILE__).'/../../Fixtures'); $GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup'] = 'mat2='.$this->fixturesFolder.'/mat2'; } - protected function tearDown() + protected function tearDown(): void { - parent::tearDown(); - if (file_exists($this->fixturesFolder.'/mat2_failure')) { unlink($this->fixturesFolder.'/mat2_failure'); } + + parent::tearDown(); } /** * @test */ - public function cleanupFile() + public function cleanupFile(): void { $file = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); $file @@ -109,7 +78,7 @@ public function cleanupFile() ->with( 'exec', [ - 'cmd' => $this->fixturesFolder.'/mat2 --inplace --lightweight \''.$this->fixturesFolder.'/testPath\'', + 'cmd' => $this->fixturesFolder."/mat2 --inplace --lightweight '".$this->fixturesFolder."/testPath'", 'output' => ['mat2 executed'], 'returnValue' => 0, ] @@ -120,7 +89,7 @@ public function cleanupFile() /** * @test */ - public function cleanupFileIfFailure() + public function cleanupFileIfFailure(): void { touch($this->fixturesFolder.'/mat2_failure'); $file = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); @@ -138,7 +107,7 @@ public function cleanupFileIfFailure() ->with( 'exec', [ - 'cmd' => $this->fixturesFolder.'/mat2 --inplace --lightweight \''.$this->fixturesFolder.'/testPath\'', + 'cmd' => $this->fixturesFolder."/mat2 --inplace --lightweight '".$this->fixturesFolder."/testPath'", 'output' => ['mat2 executed'], 'returnValue' => 123, ] @@ -151,7 +120,7 @@ public function cleanupFileIfFailure() * * @dataProvider canHandleFileDataProvider */ - public function canHandleFileIfSvgFileGiven(string $mimeType, bool $canHandle) + public function canHandleFileIfSvgFileGiven(string $mimeType, bool $canHandle): void { $file = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); $file diff --git a/Tests/Unit/Cleaner/RegistryTest.php b/Tests/Unit/Cleaner/RegistryTest.php index 88594b5..5c0a1d4 100644 --- a/Tests/Unit/Cleaner/RegistryTest.php +++ b/Tests/Unit/Cleaner/RegistryTest.php @@ -30,7 +30,7 @@ use DMK\Mkcleaner\Cleaner\ExiftoolAndQpdfCleaner; use DMK\Mkcleaner\Cleaner\Mat2Cleaner; use DMK\Mkcleaner\Cleaner\Registry; -use Nimut\TestingFramework\TestCase\UnitTestCase; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** * Class RegistryTest. @@ -41,7 +41,9 @@ */ class RegistryTest extends UnitTestCase { - protected function tearDown() + protected bool $resetSingletonInstances = true; + + protected function tearDown(): void { parent::tearDown(); @@ -52,7 +54,7 @@ protected function tearDown() /** * @test */ - public function registerAndUnregisterCleaner() + public function registerAndUnregisterCleaner(): void { Registry::registerCleaner(Mat2Cleaner::class, 50); Registry::registerCleaner(ExiftoolAndQpdfCleaner::class, 75); @@ -71,7 +73,7 @@ public function registerAndUnregisterCleaner() /** * @test */ - public function registerCleanerWithSamePriorityThrowsException() + public function registerCleanerWithSamePriorityThrowsException(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Priority 50 for cleaner DMK\Mkcleaner\Cleaner\Mat2Cleaner already in use'); @@ -82,7 +84,7 @@ public function registerCleanerWithSamePriorityThrowsException() /** * @test */ - public function registerCleanerWithoutCleanerInterfaceThrowsException() + public function registerCleanerWithoutCleanerInterfaceThrowsException(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Cleaner stdClass needs to implement DMK\Mkcleaner\Cleaner\CleanerInterface'); diff --git a/Tests/Unit/Task/CleanerTaskTest.php b/Tests/Unit/Command/CleanerCommandTest.php similarity index 56% rename from Tests/Unit/Task/CleanerTaskTest.php rename to Tests/Unit/Command/CleanerCommandTest.php index 2f8f2a8..a26ceb3 100644 --- a/Tests/Unit/Task/CleanerTaskTest.php +++ b/Tests/Unit/Command/CleanerCommandTest.php @@ -27,65 +27,30 @@ namespace DMK\Mkcleaner\Tests\Task; +use DMK\Mkcleaner\Command\CleanerCommand; +use DMK\Mkcleaner\Command\Helper; use DMK\Mkcleaner\Service\CleanerService; -use DMK\Mkcleaner\Task\CleanerTask; -use DMK\Mkcleaner\Task\Helper; -use Nimut\TestingFramework\TestCase\UnitTestCase; -use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\OutputInterface; use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Resource\Folder; -use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** - * Class CleanerTaskTest. + * Class CleanerCommandTest. * * @author Hannes Bochmann * @license http://www.gnu.org/licenses/lgpl.html * GNU Lesser General Public License, version 3 or later */ -class CleanerTaskTest extends UnitTestCase +class CleanerCommandTest extends UnitTestCase { - /** - * @var CleanerTask|MockObject - */ - protected $task; - - protected function setUp() - { - parent::setUp(); - - // We need a mock to disable the constructor - $this->task = $this->getMockBuilder(CleanerTask::class) - // dummy method - ->setMethods(['getTaskUid']) - ->disableOriginalConstructor() - ->getMock(); - } - /** * @test */ - public function getAdditionalInformation() - { - $GLOBALS['LANG'] = $this->getAccessibleMock(LanguageService::class, ['sL'], [], '', false); - $GLOBALS['LANG'] - ->expects(self::once()) - ->method('sL') - ->with('LLL:EXT:mkcleaner/Resources/Private/Language/locallang.xlf:label.CleanerTask.foldersToClean') - ->willReturn('label'); - - $this->task->setFoldersToClean('paths'); - self::assertSame( - 'test'.CRLF.'label: '.CRLF.'paths', - $this->task->getAdditionalInformation('test') - ); - } - - /** - * @test - */ - public function execute() + public function execute(): void { + $GLOBALS['LANG'] = $this->createMock(LanguageService::class); $helper = $this->getMockBuilder(Helper::class) ->disableOriginalConstructor() ->getMock(); @@ -94,9 +59,8 @@ public function execute() $helper ->expects(self::once()) ->method('getFolderObjectsFromCombinedIdentifiers') - ->with('path1'.CRLF.'path2') + ->with(['path1', 'path2']) ->willReturn([$firstFolder, $secondFolder]); - GeneralUtility::addInstance(Helper::class, $helper); $cleanerService = $this->getMockBuilder(CleanerService::class) ->disableOriginalConstructor() @@ -105,9 +69,11 @@ public function execute() ->expects(self::exactly(2)) ->method('cleanupFolder') ->withConsecutive([$firstFolder], [$secondFolder]); - GeneralUtility::setSingletonInstance(CleanerService::class, $cleanerService); - $this->task->setFoldersToClean('path1'.CRLF.'path2'); - self::assertTrue($this->task->execute()); + $command = $this->getAccessibleMock(CleanerCommand::class, ['run'], [$cleanerService, $helper]); + $input = new ArrayInput(['foldersToClean' => ['path1', 'path2']]); + $input->bind($command->getDefinition()); + + self::assertTrue(0 === $command->_call('execute', $input, $this->createMock(OutputInterface::class))); } } diff --git a/Tests/Unit/Task/HelperTest.php b/Tests/Unit/Command/HelperTest.php similarity index 89% rename from Tests/Unit/Task/HelperTest.php rename to Tests/Unit/Command/HelperTest.php index 2501ab1..142411a 100644 --- a/Tests/Unit/Task/HelperTest.php +++ b/Tests/Unit/Command/HelperTest.php @@ -25,11 +25,11 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -namespace DMK\Mkcleaner\Tests\Task; +namespace DMK\Mkcleaner\Tests\Command; -use DMK\Mkcleaner\Task\Helper; -use Nimut\TestingFramework\TestCase\UnitTestCase; +use DMK\Mkcleaner\Command\Helper; use TYPO3\CMS\Core\Resource\ResourceFactory; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** * Class HelperTest. @@ -43,7 +43,7 @@ class HelperTest extends UnitTestCase /** * @test */ - public function getFolderObjectsFromCombinedIdentifiers() + public function getFolderObjectsFromCombinedIdentifiers(): void { $resourceFactory = $this->getMockBuilder(ResourceFactory::class) ->disableOriginalConstructor() @@ -56,7 +56,7 @@ public function getFolderObjectsFromCombinedIdentifiers() ->withConsecutive(['first'], ['second']) ->willReturnOnConsecutiveCalls($firstFolder, $secondFolder); - $folders = (new Helper($resourceFactory))->getFolderObjectsFromCombinedIdentifiers('first'.CRLF.'second'); + $folders = (new Helper($resourceFactory))->getFolderObjectsFromCombinedIdentifiers(['first', 'second']); self::assertCount(2, $folders); self::assertSame($firstFolder, $folders[0]); self::assertSame($secondFolder, $folders[1]); diff --git a/Tests/Unit/SignalSlot/ResourceStorageTest.php b/Tests/Unit/EventListener/UploadedFileEventListenerTest.php similarity index 72% rename from Tests/Unit/SignalSlot/ResourceStorageTest.php rename to Tests/Unit/EventListener/UploadedFileEventListenerTest.php index 53d9143..b08ead6 100644 --- a/Tests/Unit/SignalSlot/ResourceStorageTest.php +++ b/Tests/Unit/EventListener/UploadedFileEventListenerTest.php @@ -25,27 +25,28 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -namespace DMK\Mkcleaner\Tests\SignalSlot; +namespace DMK\Mkcleaner\Tests\EventListener; +use DMK\Mkcleaner\EventListener\UploadedFileEventListener; use DMK\Mkcleaner\Service\CleanerService; -use DMK\Mkcleaner\SignalSlot\ResourceStorage; -use Nimut\TestingFramework\TestCase\UnitTestCase; +use TYPO3\CMS\Core\Resource\Event\AfterFileAddedEvent; use TYPO3\CMS\Core\Resource\File; -use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Resource\Folder; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** - * Class ResourceStorageTest. + * Class UploadedFileEventListenerTest. * * @author Hannes Bochmann * @license http://www.gnu.org/licenses/lgpl.html * GNU Lesser General Public License, version 3 or later */ -class ResourceStorageTest extends UnitTestCase +class UploadedFileEventListenerTest extends UnitTestCase { /** * @test */ - public function cleanupFile() + public function cleanupFile(): void { $file = $this->getMockBuilder(File::class) ->disableOriginalConstructor() @@ -57,8 +58,10 @@ public function cleanupFile() ->expects(self::once()) ->method('cleanupFile') ->with($file); - GeneralUtility::setSingletonInstance(CleanerService::class, $cleanerService); - GeneralUtility::makeInstance(ResourceStorage::class)->cleanupFile($file); + $event = new AfterFileAddedEvent($file, $this->createMock(Folder::class)); + $eventListener = new UploadedFileEventListener($cleanerService); + + $eventListener->cleanupFile($event); } } diff --git a/Tests/Unit/Service/CleanerServiceTest.php b/Tests/Unit/Service/CleanerServiceTest.php index 377cb8e..7357b31 100644 --- a/Tests/Unit/Service/CleanerServiceTest.php +++ b/Tests/Unit/Service/CleanerServiceTest.php @@ -31,10 +31,10 @@ use DMK\Mkcleaner\Cleaner\Mat2Cleaner; use DMK\Mkcleaner\Cleaner\Registry; use DMK\Mkcleaner\Service\CleanerService; -use Nimut\TestingFramework\TestCase\UnitTestCase; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** * Class Mat2ServiceTest. @@ -45,7 +45,9 @@ */ class CleanerServiceTest extends UnitTestCase { - protected function tearDown() + protected bool $resetSingletonInstances = true; + + protected function tearDown(): void { parent::tearDown(); @@ -56,7 +58,7 @@ protected function tearDown() /** * @test */ - public function cleanupFile() + public function cleanupFile(): void { $file = $this->getMockBuilder(File::class) ->disableOriginalConstructor() @@ -98,7 +100,7 @@ public function cleanupFile() /** * @test */ - public function cleanupFolder() + public function cleanupFolder(): void { $firstFile = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); $secondFile = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock(); diff --git a/Tests/Unit/Task/CleanupTaskFieldProviderTest.php b/Tests/Unit/Task/CleanupTaskFieldProviderTest.php deleted file mode 100644 index 2afe656..0000000 --- a/Tests/Unit/Task/CleanupTaskFieldProviderTest.php +++ /dev/null @@ -1,175 +0,0 @@ - - * All rights reserved - * - * This file is part of the "mkcleaner" Extension for TYPO3 CMS. - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNU Lesser General Public License can be found at - * www.gnu.org/licenses/lgpl.html - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - */ - -namespace DMK\Mkcleaner\Tests\Task; - -use DMK\Mkcleaner\Task\CleanerTask; -use DMK\Mkcleaner\Task\CleanerTaskFieldProvider; -use DMK\Mkcleaner\Task\Helper; -use Nimut\TestingFramework\TestCase\UnitTestCase; -use TYPO3\CMS\Core\Localization\LanguageService; -use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController; - -/** - * Class CleanerTaskTest. - * - * @author Hannes Bochmann - * @license http://www.gnu.org/licenses/lgpl.html - * GNU Lesser General Public License, version 3 or later - */ -class CleanerTaskFieldProviderTest extends UnitTestCase -{ - /** - * @test - */ - public function saveAdditionalFields() - { - $task = $this->getMockBuilder(CleanerTask::class) - ->setMethods(['setFoldersToClean']) - ->disableOriginalConstructor() - ->getMock(); - $task - ->expects(self::once()) - ->method('setFoldersToClean') - ->with('testPath'); - $provider = new CleanerTaskFieldProvider(); - $provider->saveAdditionalFields(['foldersToClean' => 'testPath'], $task); - } - - /** - * @test - */ - public function validateAdditionalFieldsWithInvalidData() - { - $GLOBALS['LANG'] = $this->getAccessibleMock(LanguageService::class, ['sL'], [], '', false); - $GLOBALS['LANG'] - ->expects(self::once()) - ->method('sL') - ->with('LLL:EXT:mkcleaner/Resources/Private/Language/locallang.xlf:message.CleanerTask.foldersToClean.invalid') - ->willReturn('message'); - - $helper = $this->getMockBuilder(Helper::class) - ->disableOriginalConstructor() - ->getMock(); - $helper - ->expects(self::once()) - ->method('getFolderObjectsFromCombinedIdentifiers') - ->with('/') - ->willThrowException(new \Exception('folder not found')); - - $moduleController = $this->getMockBuilder(SchedulerModuleController::class) - ->disableOriginalConstructor() - ->getMock(); - $moduleController - ->expects(self::once()) - ->method('addMessage') - ->with('message', 2); - $provider = new CleanerTaskFieldProvider($helper); - $submittedData = ['foldersToClean' => '/']; - self::assertFalse($provider->validateAdditionalFields($submittedData, $moduleController)); - } - - /** - * @test - */ - public function validateAdditionalFields() - { - $moduleController = $this->getMockBuilder(SchedulerModuleController::class) - ->disableOriginalConstructor() - ->getMock(); - $moduleController - ->expects(self::never()) - ->method('addMessage'); - $helper = $this->getMockBuilder(Helper::class) - ->disableOriginalConstructor() - ->getMock(); - $provider = new CleanerTaskFieldProvider($helper); - $submittedData = ['foldersToClean' => '/']; - self::assertTrue($provider->validateAdditionalFields($submittedData, $moduleController)); - } - - /** - * @test - */ - public function getAdditionalFields() - { - $moduleController = $this->getMockBuilder(SchedulerModuleController::class) - ->disableOriginalConstructor() - ->getMock(); - $task = $this->getMockBuilder(CleanerTask::class) - ->setMethods(['getFoldersToClean']) - ->disableOriginalConstructor() - ->getMock(); - $provider = new CleanerTaskFieldProvider(); - $taskInfo = ['dummy' => 'test']; - self::assertSame( - [ - 'foldersToClean' => [ - 'code' => '', - 'label' => 'LLL:EXT:mkcleaner/Resources/Private/Language/locallang.xlf:label.CleanerTask.foldersToClean', - 'cshKey' => 'csh_mkcleaner', - 'cshLabel' => 'label.CleanerTask.foldersToClean.csh', - ], - ], - $provider->getAdditionalFields($taskInfo, $task, $moduleController) - ); - self::assertSame(['dummy' => 'test'], $taskInfo); - } - - /** - * @test - */ - public function getAdditionalFieldsWhenEditingTask() - { - $moduleController = $this->getMockBuilder(SchedulerModuleController::class) - ->disableOriginalConstructor() - ->getMock(); - $moduleController->CMD = 'edit'; - $task = $this->getMockBuilder(CleanerTask::class) - ->setMethods(['getFoldersToClean']) - ->disableOriginalConstructor() - ->getMock(); - $task - ->expects(self::once()) - ->method('getFoldersToClean') - ->willReturn(''); - $provider = new CleanerTaskFieldProvider(); - $taskInfo = ['dummy' => 'test']; - self::assertSame( - [ - 'foldersToClean' => [ - 'code' => '', - 'label' => 'LLL:EXT:mkcleaner/Resources/Private/Language/locallang.xlf:label.CleanerTask.foldersToClean', - 'cshKey' => 'csh_mkcleaner', - 'cshLabel' => 'label.CleanerTask.foldersToClean.csh', - ], - ], - $provider->getAdditionalFields($taskInfo, $task, $moduleController) - ); - self::assertSame(['dummy' => 'test', 'foldersToClean' => ''], $taskInfo); - } -} diff --git a/composer.json b/composer.json index d4acc08..fa4acf9 100644 --- a/composer.json +++ b/composer.json @@ -33,9 +33,11 @@ "phpcompatibility/php-compatibility": "^9.3.5", "phpmd/phpmd": "^2.13", "phpstan/phpstan": "^1.9", - "phpstan/extension-installer": "^1.1", + "phpstan/extension-installer": "^1.3", "saschaegerer/phpstan-typo3": "^1.8", - "nimut/testing-framework": "^6.0" + "typo3/testing-framework": "^6.0 | ^7.0", + "ssch/typo3-rector": "^2.5", + "rector/rector": "^1.0" }, "autoload": { "psr-4": { @@ -84,22 +86,26 @@ "[ -e .Build/bin/php-cs-fixer ] || composer update --ansi", ".Build/bin/php-cs-fixer fix -v --dry-run --diff --ansi" ], + "test:rector": [ + "[ -e .Build/bin/rector ] || composer update --ansi", + ".Build/bin/rector process --dry-run" + ], "test:phpcompatibility": [ - "@test:phpcompatibility:7.2", - "@test:phpcompatibility:7.3", - "@test:phpcompatibility:7.4" + "@test:phpcompatibility:8.1", + "@test:phpcompatibility:8.2", + "@test:phpcompatibility:8.3" ], - "test:phpcompatibility:7.2": [ + "test:phpcompatibility:8.1": [ "[ -e .Build/bin/phpcs ] || composer update", - ".Build/bin/phpcs --ignore=.Build/*,Resources/Private/PHP/* -p . --standard=.Build/vendor/phpcompatibility/php-compatibility/PHPCompatibility --runtime-set testVersion 7.2" + ".Build/bin/phpcs --ignore=.Build/*,Resources/Private/PHP/* -p . --standard=.Build/vendor/phpcompatibility/php-compatibility/PHPCompatibility --runtime-set testVersion 8.1" ], - "test:phpcompatibility:7.3": [ + "test:phpcompatibility:8.2": [ "[ -e .Build/bin/phpcs ] || composer update", - ".Build/bin/phpcs --ignore=.Build/*,Resources/Private/PHP/* -p . --standard=.Build/vendor/phpcompatibility/php-compatibility/PHPCompatibility --runtime-set testVersion 7.3" + ".Build/bin/phpcs --ignore=.Build/*,Resources/Private/PHP/* -p . --standard=.Build/vendor/phpcompatibility/php-compatibility/PHPCompatibility --runtime-set testVersion 8.2" ], - "test:phpcompatibility:7.4": [ + "test:phpcompatibility:8.3": [ "[ -e .Build/bin/phpcs ] || composer update", - ".Build/bin/phpcs --ignore=.Build/*,Resources/Private/PHP/* -p . --standard=.Build/vendor/phpcompatibility/php-compatibility/PHPCompatibility --runtime-set testVersion 7.4" + ".Build/bin/phpcs --ignore=.Build/*,Resources/Private/PHP/* -p . --standard=.Build/vendor/phpcompatibility/php-compatibility/PHPCompatibility --runtime-set testVersion 8.3" ], "test:phpmd": [ "[ -e .Build/bin/phpmd ] || composer update --ansi", @@ -115,6 +121,7 @@ ], "test": [ "@test:phpcs", + "@test:rector", "@test:phpcompatibility", "@test:phpmd", "@test:phpstan", @@ -124,7 +131,12 @@ "[ -e .Build/bin/php-cs-fixer ] || composer update --ansi", ".Build/bin/php-cs-fixer fix -v" ], + "fix:rector": [ + "[ -e .Build/bin/rector ] || composer update --ansi", + ".Build/bin/rector process" + ], "fix": [ + "@fix:rector", "@fix:phpcs" ] } diff --git a/ext_localconf.php b/ext_localconf.php index 1b87ebd..958204e 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -28,8 +28,9 @@ if (!defined('TYPO3')) { exit('Access denied.'); } + call_user_func( - function () { + function (): void { DMK\Mkcleaner\Cleaner\Registry::registerCleaner(DMK\Mkcleaner\Cleaner\Mat2Cleaner::class, 50); DMK\Mkcleaner\Cleaner\Registry::registerCleaner(DMK\Mkcleaner\Cleaner\ExiftoolAndQpdfCleaner::class, 75); } diff --git a/ext_tables.php b/ext_tables.php index 925f7c4..9d44a87 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -25,7 +25,7 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -defined('TYPO3') or exit; +defined('TYPO3') || exit; if (TYPO3_MODE === 'BE') { // Add context sensitive help (csh) to the scheduler module diff --git a/phpunit.xml b/phpunit.xml index 28cee9f..045aaea 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,7 +1,6 @@ + * All rights reserved + * + * This file is part of the "mkcleaner" Extension for TYPO3 CMS. + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNU Lesser General Public License can be found at + * www.gnu.org/licenses/lgpl.html + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; +use Rector\Config\RectorConfig; +use Rector\PostRector\Rector\NameImportingPostRector; +use Rector\Set\ValueObject\LevelSetList; +use Rector\Set\ValueObject\SetList; +use Rector\ValueObject\PhpVersion; +use Ssch\TYPO3Rector\CodeQuality\General\ConvertImplicitVariablesToExplicitGlobalsRector; +use Ssch\TYPO3Rector\CodeQuality\General\ExtEmConfRector; +use Ssch\TYPO3Rector\Configuration\Typo3Option; +use Ssch\TYPO3Rector\Set\Typo3LevelSetList; + +return static function (RectorConfig $rectorConfig): void { + $rectorConfig->paths([__DIR__]); + + $rectorConfig->phpVersion(PhpVersion::PHP_81); + + $rectorConfig->sets([ + LevelSetList::UP_TO_PHP_83, + SetList::CODE_QUALITY, + SetList::CODING_STYLE, + SetList::DEAD_CODE, + SetList::STRICT_BOOLEANS, + SetList::PHP_82, + SetList::PRIVATIZATION, + SetList::TYPE_DECLARATION, + SetList::EARLY_RETURN, + SetList::INSTANCEOF, + Typo3LevelSetList::UP_TO_TYPO3_11, + ]); + + $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); + $rectorConfig->ruleWithConfiguration( + ExtEmConfRector::class, + [ + ExtEmConfRector::PHP_VERSION_CONSTRAINT => '8.1.0-8.3.99', + ExtEmConfRector::TYPO3_VERSION_CONSTRAINT => '11.5.0-12.4.99', + ExtEmConfRector::ADDITIONAL_VALUES_TO_BE_REMOVED => [], + ] + ); + $rectorConfig->rule(ConvertImplicitVariablesToExplicitGlobalsRector::class); + + $rectorConfig->phpstanConfig(Typo3Option::PHPSTAN_FOR_RECTOR_PATH); + $rectorConfig->phpstanConfig(__DIR__.'/phpstan.neon'); + + $rectorConfig->skip([ + // no namespace imports for these files: + NameImportingPostRector::class => [ + 'ext_localconf.php', + 'ext_tables.php', + 'ClassAliasMap.php', + __DIR__.'/Configuration/*.php', + __DIR__.'/Configuration/**/*.php', + ], + ]); +};