diff --git a/.travis.yml b/.travis.yml
index 808de2a..a894e02 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,16 +3,6 @@ language: php
matrix:
fast_finish: true
include:
- - php: 5.5
- env: TYPO3_VERSION=^7
- - php: 5.6
- env: TYPO3_VERSION=^7
- - php: 7.0
- env: TYPO3_VERSION=^7
- - php: 7.1
- env: TYPO3_VERSION=^7
- - php: 7.2
- env: TYPO3_VERSION=^7
- php: 7.0
env: TYPO3_VERSION=^8
- php: 7.1
@@ -21,6 +11,12 @@ matrix:
env: TYPO3_VERSION=^8
- php: 7.2
env: TYPO3_VERSION=^9
+ - php: 7.3
+ env: TYPO3_VERSION=^9
+ - php: 7.2
+ env: TYPO3_VERSION=^10
+ - php: 7.3
+ env: TYPO3_VERSION=^10
sudo: false
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc18a6e..bd3e92f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+### 1.5.0
+* **[FEATURE]** Add support for TYPO3 10.0 - Thanks to @achimfritz, @davidsteeb and @bmack from @b13 GmbH
+* **[CHANGE]** Drop support for TYPO3 7.6
+* **[CHANGE]** Rename TypoScript setup file
+* **[CHANGE]** Add compression errors and optimize flash messages
+
+### 1.4.0
+* **[FEATURE]** Add option to exclude specific folders from compression - Thanks to @achimfritz, @davidsteeb and @bmack from @b13 GmbH
+
### 1.3.0
* **[FEATURE]** Add support for TYPO3 9.5
* **[CHANGE]** Drop support of non composer installation
diff --git a/Classes/Command/CompressImagesCommand.php b/Classes/Command/CompressImagesCommand.php
new file mode 100644
index 0000000..de764f2
--- /dev/null
+++ b/Classes/Command/CompressImagesCommand.php
@@ -0,0 +1,150 @@
+setName('compressImages:compress')
+ ->setDescription('compress uncompressed images')
+ ->addArgument(
+ 'limit',
+ InputArgument::OPTIONAL,
+ 'limit of files to compress',
+ self::DEFAULT_LIMIT_TO_PROCESS
+ );
+ }
+
+ /**
+ * @throws \TYPO3\CMS\Extbase\Object\Exception
+ */
+ protected function initializeDependencies(): void
+ {
+ $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
+ $this->fileStorageRepository = $this->objectManager->get(FileStorageRepository::class);
+ $this->fileRepository = $this->objectManager->get(FileRepository::class);
+ $this->resourceFactory = $this->objectManager->get(ResourceFactory::class);
+ $this->compressImageService = $this->objectManager->get(CompressImageService::class);
+ }
+
+ /**
+ * Executes the command for adding the lock file
+ *
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ */
+ protected function execute(InputInterface $input, OutputInterface $output): void
+ {
+ $limit = (int)$input->getArgument('limit');
+ $this->initializeDependencies();
+ $settings = $this->getTypoScriptConfiguration();
+ /** @var FileStorage $fileStorage */
+ foreach ($this->fileStorageRepository->findAll() as $fileStorage) {
+ $excludeFolders = GeneralUtility::trimExplode(',', (string)$settings['excludeFolders'], true);
+ $files = $this->fileRepository->findAllNonCompressedInStorageWithLimit($fileStorage, $limit, $excludeFolders);
+ $this->compressImages($files);
+ $this->clearPageCache();
+ }
+ }
+
+ /**
+ * @param QueryResultInterface $files
+ * @return void
+ * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
+ * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
+ * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
+ * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
+ */
+ protected function compressImages(QueryResultInterface $files): void
+ {
+ /** @var FileDeletionAspect $fileDeletionAspect */
+ $fileDeletionAspect = GeneralUtility::makeInstance(FileDeletionAspect::class);
+ /** @var \Schmitzal\Tinyimg\Domain\Model\File $file */
+ foreach ($files as $file) {
+ if ($file instanceof \Schmitzal\Tinyimg\Domain\Model\File) {
+ $file = $this->resourceFactory->getFileObject($file->getUid());
+ $this->compressImageService->initializeCompression($file);
+ $fileDeletionAspect->cleanupProcessedFilesPostFileReplace($file, '');
+ }
+ }
+ }
+
+ /**
+ * Remove all processed files, so they get generated again after being compressed
+ * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheGroupException
+ */
+ protected function clearPageCache(): void
+ {
+ /** @var CacheManager $cacheManager */
+ $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
+ $cacheManager->flushCachesInGroup('pages');
+ }
+
+ /**
+ * @return array
+ * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
+ */
+ protected function getTypoScriptConfiguration(): array
+ {
+ /** @var ConfigurationManager $configurationManager */
+ $configurationManager = $this->objectManager->get(ConfigurationManager::class);
+
+ return (array)$configurationManager->getConfiguration(
+ ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
+ 'tinyimg'
+ );
+ }
+}
diff --git a/Classes/Command/CompressImagesCommandController.php b/Classes/Command/CompressImagesCommandController.php
deleted file mode 100644
index a7647bd..0000000
--- a/Classes/Command/CompressImagesCommandController.php
+++ /dev/null
@@ -1,94 +0,0 @@
-fileStorageRepository->findAll() as $fileStorage) {
- $files = $this->fileRepository->findAllNonCompressedInStorageWithLimit($fileStorage, 100);
-
- $this->compressImages($files);
-
- $this->clearProcessedFiles();
- }
- }
-
- /**
- * @param QueryResultInterface $files
- * @return void
- * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
- * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
- * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
- * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
- */
- protected function compressImages(QueryResultInterface $files)
- {
- /** @var \Schmitzal\Tinyimg\Domain\Model\File $file */
- foreach ($files as $file) {
- if ($file instanceof \Schmitzal\Tinyimg\Domain\Model\File) {
- $file = $this->resourceFactory->getFileObject($file->getUid());
- if (filesize(GeneralUtility::getFileAbsFileName($file->getPublicUrl())) > 0) {
- $this->compressImageService->initializeCompression($file);
- }
- }
- }
- }
-
- /**
- * Remove all processed files, so they get generated again after being compressed
- * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheGroupException
- */
- protected function clearProcessedFiles()
- {
- /** @var ProcessedFileRepository $repository */
- $repository = GeneralUtility::makeInstance(ProcessedFileRepository::class);
- /** @var CacheManager $cacheManager */
- $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
-
- $repository->removeAll();
- $cacheManager->flushCachesInGroup('pages');
- }
-}
diff --git a/Classes/Domain/Model/File.php b/Classes/Domain/Model/File.php
index 23d716f..b27e9a4 100644
--- a/Classes/Domain/Model/File.php
+++ b/Classes/Domain/Model/File.php
@@ -17,10 +17,15 @@ class File extends \TYPO3\CMS\Extbase\Domain\Model\File
*/
protected $compressed = false;
+ /**
+ * @var string
+ */
+ protected $compressError = '';
+
/**
* @return int
*/
- public function getStorage()
+ public function getStorage(): int
{
return $this->storage;
}
@@ -28,7 +33,7 @@ public function getStorage()
/**
* @param int $storage
*/
- public function setStorage($storage)
+ public function setStorage(int $storage): void
{
$this->storage = $storage;
}
@@ -36,7 +41,7 @@ public function setStorage($storage)
/**
* @return bool
*/
- public function isCompressed()
+ public function isCompressed(): bool
{
return $this->compressed;
}
@@ -44,8 +49,32 @@ public function isCompressed()
/**
* @param bool $compressed
*/
- public function setCompressed($compressed)
+ public function setCompressed(bool $compressed): void
{
$this->compressed = $compressed;
}
+
+ /**
+ * @return string
+ */
+ public function getCompressError(): string
+ {
+ return $this->compressError;
+ }
+
+ /**
+ * @param string $compressError
+ */
+ public function setCompressError(string $compressError): void
+ {
+ $this->compressError = $compressError;
+ }
+
+ /**
+ * @return void
+ */
+ public function resetCompressError(): void
+ {
+ $this->setCompressError('');
+ }
}
diff --git a/Classes/Domain/Model/FileStorage.php b/Classes/Domain/Model/FileStorage.php
index 5ae546e..8864019 100644
--- a/Classes/Domain/Model/FileStorage.php
+++ b/Classes/Domain/Model/FileStorage.php
@@ -41,7 +41,7 @@ class FileStorage extends AbstractEntity
/**
* @return string
*/
- public function getName()
+ public function getName(): string
{
return $this->name;
}
@@ -49,7 +49,7 @@ public function getName()
/**
* @param string $name
*/
- public function setName($name)
+ public function setName(string $name)
{
$this->name = $name;
}
@@ -57,7 +57,7 @@ public function setName($name)
/**
* @return string
*/
- public function getDescription()
+ public function getDescription(): string
{
return $this->description;
}
@@ -65,7 +65,7 @@ public function getDescription()
/**
* @param string $description
*/
- public function setDescription($description)
+ public function setDescription(string $description)
{
$this->description = $description;
}
@@ -73,7 +73,7 @@ public function setDescription($description)
/**
* @return bool
*/
- public function isDefault()
+ public function isDefault(): bool
{
return $this->default;
}
@@ -81,7 +81,7 @@ public function isDefault()
/**
* @param bool $default
*/
- public function setDefault($default)
+ public function setDefault(bool $default)
{
$this->default = $default;
}
@@ -89,7 +89,7 @@ public function setDefault($default)
/**
* @return bool
*/
- public function isBrowsable()
+ public function isBrowsable(): bool
{
return $this->browsable;
}
@@ -97,7 +97,7 @@ public function isBrowsable()
/**
* @param bool $browsable
*/
- public function setBrowsable($browsable)
+ public function setBrowsable(bool $browsable)
{
$this->browsable = $browsable;
}
@@ -105,7 +105,7 @@ public function setBrowsable($browsable)
/**
* @return bool
*/
- public function isPublic()
+ public function isPublic(): bool
{
return $this->public;
}
@@ -113,7 +113,7 @@ public function isPublic()
/**
* @param bool $public
*/
- public function setPublic($public)
+ public function setPublic(bool $public)
{
$this->public = $public;
}
@@ -121,7 +121,7 @@ public function setPublic($public)
/**
* @return bool
*/
- public function isWritable()
+ public function isWritable(): bool
{
return $this->writable;
}
@@ -129,7 +129,7 @@ public function isWritable()
/**
* @param bool $writable
*/
- public function setWritable($writable)
+ public function setWritable(bool $writable)
{
$this->writable = $writable;
}
@@ -137,7 +137,7 @@ public function setWritable($writable)
/**
* @return bool
*/
- public function isOnline()
+ public function isOnline(): bool
{
return $this->online;
}
@@ -145,7 +145,7 @@ public function isOnline()
/**
* @param bool $online
*/
- public function setOnline($online)
+ public function setOnline(bool $online)
{
$this->online = $online;
}
diff --git a/Classes/Domain/Repository/FileRepository.php b/Classes/Domain/Repository/FileRepository.php
index 00f38b4..6594dac 100644
--- a/Classes/Domain/Repository/FileRepository.php
+++ b/Classes/Domain/Repository/FileRepository.php
@@ -1,8 +1,11 @@
getQuerySettings()->setRespectStoragePage(false);
@@ -24,19 +27,32 @@ public function createQuery()
/**
* @param FileStorage $storage
* @param int $limit
+ * @param array $excludeFolders
* @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
*/
- public function findAllNonCompressedInStorageWithLimit(FileStorage $storage, $limit = 100)
+ public function findAllNonCompressedInStorageWithLimit(FileStorage $storage, $limit = 100, $excludeFolders = []): QueryResultInterface
{
$query = $this->createQuery();
+
+ $excludeFoldersConstraints = [];
+ foreach ($excludeFolders as $excludeFolder) {
+ $excludeFoldersConstraints[] = $query->logicalNot($query->like('identifier', $excludeFolder . '%'));
+ }
+
$query->matching(
- $query->logicalAnd([
- $query->equals('storage', $storage),
- $query->equals('compressed', false),
- $query->equals('missing', false),
- $query->in('extension', ['png', 'jpg', 'jpeg'])
- ])
+ $query->logicalAnd(
+ array_merge(
+ [
+ $query->equals('storage', $storage),
+ $query->equals('compressed', false),
+ $query->equals('missing', false),
+ $query->equals('compress_error', ''),
+ $query->in('mime_type', ['image/png', 'image/jpeg'])
+ ],
+ $excludeFoldersConstraints
+ )
+ )
);
$query->setLimit($limit);
diff --git a/Classes/Domain/Repository/FileStorageRepository.php b/Classes/Domain/Repository/FileStorageRepository.php
index 4235a6e..5ce15a3 100644
--- a/Classes/Domain/Repository/FileStorageRepository.php
+++ b/Classes/Domain/Repository/FileStorageRepository.php
@@ -2,6 +2,7 @@
namespace Schmitzal\Tinyimg\Domain\Repository;
use TYPO3\CMS\Extbase\Persistence\Repository;
+use TYPO3\CMS\Extbase\Persistence\QueryInterface;
/**
* Class FileStorageRepository
@@ -12,7 +13,7 @@ class FileStorageRepository extends Repository
/**
* Do not respect storage pid for domain records
*/
- public function createQuery()
+ public function createQuery(): QueryInterface
{
$query = parent::createQuery();
$query->getQuerySettings()->setRespectStoragePage(false);
diff --git a/Classes/Service/CompressImageService.php b/Classes/Service/CompressImageService.php
index 8ebb614..ebff346 100644
--- a/Classes/Service/CompressImageService.php
+++ b/Classes/Service/CompressImageService.php
@@ -1,15 +1,23 @@
objectManager = $objectManager;
+ }
+
+ /**
+ * @param FileRepository $fileRepository
+ */
+ public function injectFileRepository(FileRepository $fileRepository): void
+ {
+ $this->fileRepository = $fileRepository;
+ }
+
+ /**
+ * @param PersistenceManager $persistenceManager
+ */
+ public function injectPersistenceManager(PersistenceManager $persistenceManager): void
+ {
+ $this->persistenceManager = $persistenceManager;
+ }
+
/**
* CompressImageService constructor.
* @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException
* @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException
*/
- public function initAction()
+ public function initAction(): void
{
- $this->extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['tinyimg']);
+ if (version_compare(TYPO3_version, '9', '>')) {
+ $this->extConf = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['tinyimg'];
+ } else {
+ // @extensionScannerIgnoreLine
+ $this->extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['tinyimg']);
+ }
if (ExtensionManagementUtility::isLoaded('aus_driver_amazon_s3')) {
$this->initCdn();
}
+
+ \Tinify\setKey($this->getApiKey());
+ $this->settings = $this->getTypoScriptConfiguration();
+ }
+
+ /**
+ * @return string
+ */
+ protected function getPublicPath(): string
+ {
+ if (version_compare(TYPO3_version, '9', '>')) {
+ return Environment::getPublicPath() . '/';
+ } else {
+ // @extensionScannerIgnoreLine
+ return PATH_site;
+ }
}
/**
* initialize the CDN
*/
- public function initCdn()
+ public function initCdn(): void
{
/** @var S3Client client */
$this->client = S3Client::factory(array(
@@ -84,26 +136,78 @@ public function initCdn()
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
*/
- public function initializeCompression($file)
+ public function initializeCompression($file): void
{
$this->initAction();
- \Tinify\setKey($this->getApiKey());
- $this->settings = $this->getTypoScriptConfiguration();
+ if ($this->isFileInExcludeFolder($file)) {
+ return;
+ }
- if ((int)$this->settings['debug'] === 0 &&
- in_array(strtolower($file->getExtension()), ['png', 'jpg', 'jpeg'], true)) {
- if ($this->checkForAmazonCdn($file)) {
- $this->pushToTinyPngAndStoreToCdn($file);
- } else {
- $publicUrl = PATH_site . $file->getPublicUrl();
- $source = \Tinify\fromFile($publicUrl);
- $source->toFile($publicUrl);
- $this->setCompressedForCurrentFile($file);
+ if (!in_array(strtolower($file->getMimeType()), ['image/png', 'image/jpeg'], true)) {
+ return;
+ }
+
+ if ((int)$this->settings['debug'] === 0) {
+ try {
+ $this->assureFileExists($file);
+ $originalFileSize = $file->getSize();
+ if ($this->checkForAmazonCdn($file)) {
+ $fileSize = $this->pushToTinyPngAndStoreToCdn($file);
+ } else {
+ $publicUrl = $this->getPublicPath() . urldecode($file->getPublicUrl());
+ $source = \Tinify\fromFile($publicUrl);
+ $source->toFile($publicUrl);
+ $fileSize = $this->setCompressedForCurrentFile($file);
+ }
+ if ((int)$fileSize !== 0) {
+ $percentageSaved = (int)(100 - ((100 / $originalFileSize) * $fileSize));
+ $this->addMessageToFlashMessageQueue('success', [0 => (string)$percentageSaved . '%'], FlashMessage::INFO);
+ }
+ $this->updateFileInformation($file);
+ } catch (\Exception $e) {
+ $this->saveError($file, $e);
+ $this->addMessageToFlashMessageQueue('compressionFailed', [0 => $e->getMessage()], FlashMessage::WARNING);
}
+ } else {
+ $this->addMessageToFlashMessageQueue('debugMode', [], FlashMessage::INFO);
+ }
+ }
+
+ /**
+ * @param File $file
+ * @throws \Exception
+ */
+ protected function assureFileExists(File $file): void
+ {
+ $absFileName = GeneralUtility::getFileAbsFileName(urldecode($file->getPublicUrl()));
+ if (file_exists($absFileName) === false) {
+ throw new \Exception('file not exists: ' . $absFileName, 1575270381);
+ }
+ if ((int)filesize($absFileName) === 0) {
+ throw new \Exception('filesize is 0: ' . $absFileName, 1575270380);
}
+ }
+
+
- $this->updateFileInformation($file);
+ /**
+ * @param File $file
+ * @return bool
+ */
+ protected function isFileInExcludeFolder(File $file): bool
+ {
+ if (!empty($this->settings['excludeFolders'])) {
+ $excludeFolders = GeneralUtility::trimExplode(',', $this->settings['excludeFolders'], true);
+ $identifier = $file->getIdentifier();
+ foreach ($excludeFolders as $excludeFolder) {
+ if (strpos($identifier, $excludeFolder) === 0) {
+ $this->addMessageToFlashMessageQueue('folderExcluded', [0 => $excludeFolder], FlashMessage::INFO);
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
@@ -114,11 +218,11 @@ public function initializeCompression($file)
* @param File $file
* @return bool
*/
- public function checkForAmazonCdn($file)
+ public function checkForAmazonCdn(File $file): bool
{
return ExtensionManagementUtility::isLoaded('aus_driver_amazon_s3') &&
- $this->getUseCdn() &&
- $this->checkIfFolderIsCdn($file);
+ $this->getUseCdn() &&
+ $this->checkIfFolderIsCdn($file);
}
/**
@@ -129,15 +233,17 @@ public function checkForAmazonCdn($file)
* Deletes old temp file.
*
* @param File $file
+ * @return int
+ * @throws \Exception
*/
- public function pushToTinyPngAndStoreToCdn($file)
+ public function pushToTinyPngAndStoreToCdn(File $file): int
{
// get the image
// no PATH_site as file will be provided by absolute URL of the bucket or the CDN
$publicUrl = $file->getPublicUrl();
// get the temp file and prefix with current time
- $tempFile = PATH_site . 'typo3temp' . DIRECTORY_SEPARATOR . time() .'_'. $this->getCdnFileName($publicUrl);
+ $tempFile = $this->getPublicPath() . 'typo3temp' . DIRECTORY_SEPARATOR . time() . '_' . $this->getCdnFileName($publicUrl);
$source = \Tinify\fromFile($publicUrl);
@@ -145,18 +251,16 @@ public function pushToTinyPngAndStoreToCdn($file)
$source->toFile($tempFile);
// upload to CDN
- try {
- $this->client->putObject([
- 'Bucket' => $this->extConf['bucket'],
- 'Key' => $file->getIdentifier(),
- 'SourceFile' => $tempFile
- ]);
- } catch (S3Exception $e) {
- throw new S3Exception($e->getMessage());
- }
-
+ $splFileObject = new \SplFileObject($tempFile);
+ $fileSize = $splFileObject->getSize();
+ $this->client->putObject([
+ 'Bucket' => $this->extConf['bucket'],
+ 'Key' => $file->getIdentifier(),
+ 'SourceFile' => $tempFile
+ ]);
// remove temp file
GeneralUtility::unlink_tempfile($tempFile);
+ return (int)$fileSize;
}
/**
@@ -165,7 +269,7 @@ public function pushToTinyPngAndStoreToCdn($file)
* @param File $file
* @return boolean
*/
- public function checkIfFolderIsCdn($file)
+ public function checkIfFolderIsCdn($file): bool
{
// if this is string, then we know, that there is already a file in the folder
// In this case you have to check if the object in the bucket exists
@@ -180,40 +284,40 @@ public function checkIfFolderIsCdn($file)
}
/**
- * @param $file string
+ * @param string $fileName
* @return string
*/
- public function getCdnFileName($file)
+ public function getCdnFileName(string $fileName): string
{
- return preg_replace('/^.*\/(.*)$/', '$1', $file);
+ return preg_replace('/^.*\/(.*)$/', '$1', $fileName);
}
/**
* @return string
*/
- protected function getApiKey()
+ protected function getApiKey(): string
{
- return $this->extConf['apiKey'];
+ return (string)$this->extConf['apiKey'];
}
/**
* @return boolean
*/
- protected function getUseCdn()
+ protected function getUseCdn(): bool
{
- return $this->extConf['useCdn'];
+ return (bool)$this->extConf['useCdn'];
}
/**
* @return array
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
*/
- protected function getTypoScriptConfiguration()
+ protected function getTypoScriptConfiguration(): array
{
/** @var ConfigurationManager $configurationManager */
$configurationManager = $this->objectManager->get(ConfigurationManager::class);
- return $configurationManager->getConfiguration(
+ return (array)$configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
'tinyimg'
);
@@ -222,7 +326,7 @@ protected function getTypoScriptConfiguration()
/**
* @param File $file
*/
- protected function updateFileInformation($file)
+ protected function updateFileInformation(File $file): void
{
/** @var Indexer $fileIndexer */
$fileIndexer = $this->objectManager->get(Indexer::class, $file->getStorage());
@@ -233,13 +337,78 @@ protected function updateFileInformation($file)
* @param File $file
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
+ * @return int
*/
- protected function setCompressedForCurrentFile(File $file)
+ protected function setCompressedForCurrentFile(File $file): ?int
{
/** @var \Schmitzal\Tinyimg\Domain\Model\File $extbaseFileObject */
$extbaseFileObject = $this->fileRepository->findByUid($file->getUid());
$extbaseFileObject->setCompressed(true);
+ $extbaseFileObject->resetCompressError();
+ $this->fileRepository->update($extbaseFileObject);
+ $this->persistenceManager->persistAll();
+ try {
+ $splFileObject = new \SplFileObject(GeneralUtility::getFileAbsFileName($file->getPublicUrl()));
+ return (int)$splFileObject->getSize();
+ } catch (\Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ protected function isCli(): bool
+ {
+ if (version_compare(TYPO3_version, '9', '>')) {
+ return Environment::isCli();
+ } else {
+ return php_sapi_name() === 'cli';
+ }
+ }
+
+ /**
+ * @param string $key
+ * @param array $replaceMarkers
+ * @param int $severity
+ * @throws \TYPO3\CMS\Core\Exception
+ */
+ protected function addMessageToFlashMessageQueue($key, array $replaceMarkers = [], $severity = FlashMessage::ERROR): void
+ {
+ if ($this->isCli()) {
+ return;
+ }
+
+ $localizationUtility = GeneralUtility::makeInstance(LocalizationUtility::class);
+ $message = $localizationUtility->translate(
+ 'LLL:EXT:tinyimg/Resources/Private/Language/locallang.xlf:flashMessage.message.' . $key,
+ null,
+ $replaceMarkers
+ );
+ $flashMessage = GeneralUtility::makeInstance(
+ FlashMessage::class,
+ $message,
+ $localizationUtility->translate('LLL:EXT:tinyimg/Resources/Private/Language/locallang.xlf:flashMessage.title'),
+ $severity,
+ true
+ );
+
+ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
+ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
+ $defaultFlashMessageQueue->enqueue($flashMessage);
+ }
+
+ /**
+ * @param File $file
+ * @param \Exception $e
+ */
+ protected function saveError(File $file, \Exception $e)
+ {
+ /** @var \Schmitzal\Tinyimg\Domain\Model\File $extbaseFileObject */
+ $extbaseFileObject = $this->fileRepository->findByUid($file->getUid());
+ $extbaseFileObject->setCompressed(false);
+ $extbaseFileObject->setCompressError($e->getCode() . ' : ' . $e->getMessage());
$this->fileRepository->update($extbaseFileObject);
$this->persistenceManager->persistAll();
}
diff --git a/Configuration/Commands.php b/Configuration/Commands.php
new file mode 100644
index 0000000..5fc92bd
--- /dev/null
+++ b/Configuration/Commands.php
@@ -0,0 +1,7 @@
+ [
+ 'class' => \Schmitzal\Tinyimg\Command\CompressImagesCommand::class
+ ]
+];
diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php
new file mode 100644
index 0000000..6f0dcf7
--- /dev/null
+++ b/Configuration/Extbase/Persistence/Classes.php
@@ -0,0 +1,10 @@
+ [
+ 'tableName' => 'sys_file_storage'
+ ],
+ \Schmitzal\Tinyimg\Domain\Model\File::class => [
+ 'tableName' => 'sys_file'
+ ]
+];
diff --git a/Configuration/TCA/Overrides/sys_file.php b/Configuration/TCA/Overrides/sys_file.php
index be43bb4..b804062 100644
--- a/Configuration/TCA/Overrides/sys_file.php
+++ b/Configuration/TCA/Overrides/sys_file.php
@@ -3,12 +3,23 @@
$sysFileColumns = [
'compressed' => [
'exclude' => true,
- 'label' => 'sys_file.compressed',
+ 'label' => 'Compressed',
'config' => [
'type' => 'check',
'default' => 0
]
+ ],
+ 'compress_error' => [
+ 'exclude' => true,
+ 'label' => 'Compression Error',
+ 'config' => [
+ 'type' => 'text',
+ 'default' => ''
+ ]
]
];
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('sys_file', $sysFileColumns);
\ No newline at end of file
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('sys_file', $sysFileColumns);
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('sys_file', 'compress_error', '', '');
+
+$GLOBALS['TCA']['sys_file']['interface']['showRecordFieldList'] .= ',compressed,compress_error';
diff --git a/Configuration/TypoScript/setup.ts b/Configuration/TypoScript/setup.ts
deleted file mode 100644
index 375388c..0000000
--- a/Configuration/TypoScript/setup.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-module.tx_tinyimg.settings.debug = 0
-
-[applicationContext = Development]
-module.tx_tinyimg.settings.debug = 1
-[global]
diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript
new file mode 100644
index 0000000..fa7011c
--- /dev/null
+++ b/Configuration/TypoScript/setup.typoscript
@@ -0,0 +1,16 @@
+module.tx_filelist.view {
+ templateRootPaths.0 = EXT:tinyimg/Resources/Private/Templates/
+}
+
+module.tx_tinyimg.settings {
+ debug = 0
+ excludeFolders =
+}
+
+[applicationContext == "Development"]
+ module.tx_tinyimg.settings.debug = 1
+[global]
+[like(applicationContext, "Development*")]
+ module.tx_tinyimg.settings.debug = 1
+[global]
+
diff --git a/README.md b/README.md
index d4d1c88..28d7529 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,12 @@ Make sure to have an updated index. TYPO3 comes with an index updater as a sched
Also be aware that the tinify API is limited to 500 free compressions (see note above). So on huge websites it will be reached quickly.
+## TypoScript reference
+| Setting | Type | Default | Description |
+|----------------|--------|---------|------------------------------------------------------------------------------------------------------------------------------------|
+| debug | bool | 0 | Enable or disable debugging mode. Stops extension from compressing images. Use in development mode to avoid waisting compressions. |
+| excludeFolders | string | empty | Comma-separated list of folders which should be excluded from compression. Relative from storage (e.g. fileadmin), starting with "/" (e.g. "/user_upload,/folder_under_fileadmin") |
+
## Contribution
Bugs and feature requests are welcome. Feel free to create an [issue](https://github.com/schmitzal/tinyimg/issues) and i'll have a look at it as soon as possible.
diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf
index 2f92290..eb53306 100644
--- a/Resources/Private/Language/locallang.xlf
+++ b/Resources/Private/Language/locallang.xlf
@@ -6,6 +6,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+