diff --git a/Classes/Form/Element/PickColorFromImage.php b/Classes/Form/Element/PickColorFromImage.php
old mode 100755
new mode 100644
index e9e2e4e..8e95d84
--- a/Classes/Form/Element/PickColorFromImage.php
+++ b/Classes/Form/Element/PickColorFromImage.php
@@ -15,12 +15,8 @@ namespace Evoweb\EwBase\Form\Element;
* LICENSE.txt file that was distributed with this source code.
*/
-use Psr\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
-use TYPO3\CMS\Backend\Form\Event\ModifyImageManipulationPreviewUrlEvent;
-use TYPO3\CMS\Backend\Routing\UriBuilder;
-use TYPO3\CMS\Backend\View\BackendViewFactory;
-use TYPO3\CMS\Core\Crypto\HashService;
+use TYPO3\CMS\Backend\Form\NodeFactory;
use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;
use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
use TYPO3\CMS\Core\Imaging\ImageManipulation\InvalidConfigurationException;
@@ -31,11 +27,11 @@ use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
+use TYPO3Fluid\Fluid\View\TemplateView;
+use TYPO3Fluid\Fluid\View\ViewInterface;
class PickColorFromImage extends AbstractFormElement
{
- private string $wizardRouteName = 'ajax_wizard_image_manipulation';
-
/**
* Default element configuration
*/
@@ -112,31 +108,53 @@ class PickColorFromImage extends AbstractFormElement
],
];
- public function __construct(
- private readonly BackendViewFactory $backendViewFactory,
- private readonly UriBuilder $uriBuilder,
- private readonly EventDispatcherInterface $eventDispatcher,
- private readonly ResourceFactory $resourceFactory,
- private readonly HashService $hashService,
- ) {}
+ protected ViewInterface $templateView;
+
+ public function __construct(NodeFactory $nodeFactory, array $data)
+ {
+ parent::__construct($nodeFactory, $data);
+ // Would be great, if we could inject the view here, but since the constructor is in the interface, we can't
+ // @todo: It's unfortunate we're using Typo3Fluid TemplateView directly here. We can't
+ // inject BackendViewFactory here since __construct() is polluted by NodeInterface.
+ // Remove __construct() from NodeInterface to have DI, then use BackendViewFactory here.
+ $view = GeneralUtility::makeInstance(TemplateView::class);
+ $templatePaths = $view->getRenderingContext()->getTemplatePaths();
+ $templatePaths
+ ->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:ew_base/Resources/Private/Templates')]);
+ $templatePaths
+ ->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:ew_base/Resources/Private/Partials')]);
+ $this->templateView = $view;
+ }
- /**
- * @throws InvalidConfigurationException
- */
public function render(): array
{
$resultArray = $this->initializeResultArray();
$parameterArray = $this->data['parameterArray'];
$config = $this->populateConfiguration($parameterArray['fieldConf']['config']);
+ $fieldId = StringUtility::getUniqueId('formengine-color-');
- $file = $this->getFile($this->data['databaseRow'], $config['imageField']);
+ $file = $this->getFileObject($this->data['databaseRow'], $config['imageField']);
if (!$file) {
+ $languageService = $this->getLanguageService();
+ $label = $languageService->sL(
+ 'LLL:EXT:ew_base/Resources/Private/Language/locallang_db.xlf:imageField.empty'
+ );
+ $fieldLabel = $this->data['processedTca']['columns'][$config['imageField']]['label'];
+ $resultArray['html'] = '
+
+ ';
// Early return in case we do not find a file
return $resultArray;
}
- $config = $this->processConfiguration($config, $parameterArray['itemFormElValue'], $file);
-
$fieldInformationResult = $this->renderFieldInformation();
$fieldInformationHtml = $fieldInformationResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
@@ -149,6 +167,14 @@ class PickColorFromImage extends AbstractFormElement
$fieldWizardHtml = $fieldWizardResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
+ $width = $this->formMaxWidth(
+ MathUtility::forceIntegerInRange(
+ $config['size'] ?? $this->defaultInputWidth,
+ $this->minimumInputWidth,
+ $this->maxInputWidth
+ )
+ );
+
$arguments = [
'fieldInformation' => $fieldInformationHtml,
'fieldControl' => $fieldControlHtml,
@@ -167,15 +193,10 @@ class PickColorFromImage extends AbstractFormElement
'validation' => '[]',
],
'config' => $config,
- 'wizardUri' => $this->getWizardUri(),
- 'wizardPayload' => json_encode($this->getWizardPayload($config['cropVariants'], $file)),
- 'previewUrl' => $this->eventDispatcher->dispatch(
- new ModifyImageManipulationPreviewUrlEvent($this->data['databaseRow'], $config, $file)
- )->getPreviewUrl(),
+ 'width' => $width,
];
if ($arguments['isAllowedFileExtension']) {
- $fieldId = StringUtility::getUniqueId('formengine-color-');
$resultArray['stylesheetFiles'][] =
'EXT:ew_base/Resources/Public/JavaScript/form-engine/element/pick-color-from-image.css';
$resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create(
@@ -191,14 +212,14 @@ class PickColorFromImage extends AbstractFormElement
$arguments['formEngine']['validation'] = $this->getValidationDataAsJsonString(['required' => true]);
}
}
- $view = $this->backendViewFactory->create($this->data['request']);
- $view->assignMultiple($arguments);
- $resultArray['html'] = $view->render('Form/ImageManipulationElement');
+
+ $this->templateView->assignMultiple($arguments);
+ $resultArray['html'] = $this->templateView->render('Form/ImageManipulationElement');
return $resultArray;
}
- protected function getFile(array $row, string $fieldName): ?File
+ protected function getFileObject(array $row, string $fieldName): ?File
{
$file = null;
$fileUid = !empty($row[$fieldName]) ? $row[$fieldName] : null;
@@ -207,26 +228,21 @@ class PickColorFromImage extends AbstractFormElement
}
if (MathUtility::canBeInterpretedAsInteger($fileUid)) {
try {
- $file = $this->resourceFactory->getFileObject($fileUid);
+ $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
+ $fileReference = $resourceFactory->getFileReferenceObject($fileUid);
+ $file = $fileReference->getOriginalFile();
} catch (FileDoesNotExistException | \InvalidArgumentException) {
}
}
return $file;
}
- /**
- * @throws InvalidConfigurationException
- */
protected function populateConfiguration(array $baseConfiguration): array
{
$defaultConfig = self::$defaultConfig;
-
- // If ratios are set do not add default options
- if (isset($baseConfiguration['cropVariants'])) {
- unset($defaultConfig['cropVariants']);
- }
-
$config = array_replace_recursive($defaultConfig, $baseConfiguration);
+ $imageConfig = $this->data['processedTca']['columns'][$config['imageField']];
+ $config['cropVariants'] = $imageConfig['config']['cropVariants'] ?? $defaultConfig['cropVariants'];
if (!is_array($config['cropVariants'])) {
throw new InvalidConfigurationException('Crop variants configuration must be an array', 1485377267);
@@ -264,8 +280,8 @@ class PickColorFromImage extends AbstractFormElement
$config['cropVariants'] = $cropVariants;
- // By default, we allow all image extensions that can be handled by the GFX functionality
$config['allowedExtensions'] ??= $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
+
return $config;
}
@@ -283,22 +299,4 @@ class PickColorFromImage extends AbstractFormElement
);
return $config;
}
-
- protected function getWizardUri(): string
- {
- return (string)$this->uriBuilder->buildUriFromRoute($this->wizardRouteName);
- }
-
- protected function getWizardPayload(array $cropVariants, File $image): array
- {
- $uriArguments = [];
- $arguments = [
- 'cropVariants' => $cropVariants,
- 'image' => $image->getUid(),
- ];
- $uriArguments['arguments'] = json_encode($arguments);
- $uriArguments['signature'] = $this->hashService->hmac((string)($uriArguments['arguments']), $this->wizardRouteName);
-
- return $uriArguments;
- }
}
diff --git a/Classes/Form/Element/PickColorFromImagePre13.php b/Classes/Form/Element/PickColorFromImagePre13.php
deleted file mode 100644
index ac81de5..0000000
--- a/Classes/Form/Element/PickColorFromImagePre13.php
+++ /dev/null
@@ -1,304 +0,0 @@
- 'image',
- 'cropVariants' => [
- 'default' => [
- 'title' =>
- 'LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:imwizard.crop_variant.default',
- 'allowedAspectRatios' => [
- '16:9' => [
- 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:imwizard.ratio.16_9',
- 'value' => 16 / 9,
- ],
- '3:2' => [
- 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:imwizard.ratio.3_2',
- 'value' => 3 / 2,
- ],
- '4:3' => [
- 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:imwizard.ratio.4_3',
- 'value' => 4 / 3,
- ],
- '1:1' => [
- 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:imwizard.ratio.1_1',
- 'value' => 1.0,
- ],
- 'NaN' => [
- 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_wizards.xlf:imwizard.ratio.free',
- 'value' => 0.0,
- ],
- ],
- 'selectedRatio' => 'NaN',
- 'cropArea' => [
- 'x' => 0.0,
- 'y' => 0.0,
- 'width' => 1.0,
- 'height' => 1.0,
- ],
- ],
- ],
- ];
-
- /**
- * Default field information enabled for this element.
- *
- * @var array
- */
- protected $defaultFieldInformation = [
- 'tcaDescription' => [
- 'renderType' => 'tcaDescription',
- ],
- ];
-
- /**
- * Default field wizards enabled for this element.
- *
- * @var array
- */
- protected $defaultFieldWizard = [
- 'localizationStateSelector' => [
- 'renderType' => 'localizationStateSelector',
- ],
- 'otherLanguageContent' => [
- 'renderType' => 'otherLanguageContent',
- 'after' => [
- 'localizationStateSelector',
- ],
- ],
- 'defaultLanguageDifferences' => [
- 'renderType' => 'defaultLanguageDifferences',
- 'after' => [
- 'otherLanguageContent',
- ],
- ],
- ];
-
- protected ViewInterface $templateView;
-
- public function __construct(NodeFactory $nodeFactory, array $data)
- {
- parent::__construct($nodeFactory, $data);
- // Would be great, if we could inject the view here, but since the constructor is in the interface, we can't
- // @todo: It's unfortunate we're using Typo3Fluid TemplateView directly here. We can't
- // inject BackendViewFactory here since __construct() is polluted by NodeInterface.
- // Remove __construct() from NodeInterface to have DI, then use BackendViewFactory here.
- $view = GeneralUtility::makeInstance(TemplateView::class);
- $templatePaths = $view->getRenderingContext()->getTemplatePaths();
- $templatePaths
- ->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:ew_base/Resources/Private/Templates')]);
- $templatePaths
- ->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:ew_base/Resources/Private/Partials')]);
- $this->templateView = $view;
- }
-
- public function render(): array
- {
- $resultArray = $this->initializeResultArray();
- $parameterArray = $this->data['parameterArray'];
- $config = $this->populateConfiguration($parameterArray['fieldConf']['config']);
- $fieldId = StringUtility::getUniqueId('formengine-color-');
-
- $file = $this->getFileObject($this->data['databaseRow'], $config['imageField']);
- if (!$file) {
- $languageService = $this->getLanguageService();
- $label = $languageService->sL(
- 'LLL:EXT:ew_base/Resources/Private/Language/locallang_db.xlf:imageField.empty'
- );
- $fieldLabel = $this->data['processedTca']['columns'][$config['imageField']]['label'];
- $resultArray['html'] = '
-
- ';
- // Early return in case we do not find a file
- return $resultArray;
- }
-
- $fieldInformationResult = $this->renderFieldInformation();
- $fieldInformationHtml = $fieldInformationResult['html'];
- $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
-
- $fieldControlResult = $this->renderFieldControl();
- $fieldControlHtml = $fieldControlResult['html'];
- $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
-
- $fieldWizardResult = $this->renderFieldWizard();
- $fieldWizardHtml = $fieldWizardResult['html'];
- $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
-
- $width = $this->formMaxWidth(
- MathUtility::forceIntegerInRange(
- $config['size'] ?? $this->defaultInputWidth,
- $this->minimumInputWidth,
- $this->maxInputWidth
- )
- );
-
- $arguments = [
- 'fieldInformation' => $fieldInformationHtml,
- 'fieldControl' => $fieldControlHtml,
- 'fieldWizard' => $fieldWizardHtml,
- 'isAllowedFileExtension' => in_array(
- strtolower($file->getExtension()),
- GeneralUtility::trimExplode(',', strtolower($config['allowedExtensions'])),
- true
- ),
- 'image' => $file,
- 'formEngine' => [
- 'field' => [
- 'value' => $parameterArray['itemFormElValue'],
- 'name' => $parameterArray['itemFormElName'],
- ],
- 'validation' => '[]',
- ],
- 'config' => $config,
- 'width' => $width,
- ];
-
- if ($arguments['isAllowedFileExtension']) {
- $resultArray['stylesheetFiles'][] =
- 'EXT:ew_base/Resources/Public/JavaScript/form-engine/element/pick-color-from-image.css';
- $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create(
- '@evoweb/ew-base/form-engine/element/pick-color-from-image.js',
- 'PickColorFromImage'
- )->instance(
- $fieldId,
- $parameterArray['itemFormElValue'],
- ($parameterArray['fieldConf']['config']['readOnly'] ?? false)
- );
- $arguments['formEngine']['field']['id'] = $fieldId;
- if ($config['required'] ?? false) {
- $arguments['formEngine']['validation'] = $this->getValidationDataAsJsonString(['required' => true]);
- }
- }
-
- $this->templateView->assignMultiple($arguments);
- $resultArray['html'] = $this->templateView->render('Form/ImageManipulationElement');
-
- return $resultArray;
- }
-
- protected function getFileObject(array $row, string $fieldName): ?File
- {
- $file = null;
- $fileUid = !empty($row[$fieldName]) ? $row[$fieldName] : null;
- if (is_array($fileUid) && isset($fileUid[0]['uid'])) {
- $fileUid = $fileUid[0]['uid'];
- }
- if (MathUtility::canBeInterpretedAsInteger($fileUid)) {
- try {
- $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
- $fileReference = $resourceFactory->getFileReferenceObject($fileUid);
- $file = $fileReference->getOriginalFile();
- } catch (FileDoesNotExistException | \InvalidArgumentException) {
- }
- }
- return $file;
- }
-
- protected function populateConfiguration(array $baseConfiguration): array
- {
- $defaultConfig = self::$defaultConfig;
- $config = array_replace_recursive($defaultConfig, $baseConfiguration);
- $imageConfig = $this->data['processedTca']['columns'][$config['imageField']];
- $config['cropVariants'] = $imageConfig['config']['cropVariants'] ?? $defaultConfig['cropVariants'];
-
- if (!is_array($config['cropVariants'])) {
- throw new InvalidConfigurationException('Crop variants configuration must be an array', 1485377267);
- }
-
- $cropVariants = [];
- foreach ($config['cropVariants'] as $id => $cropVariant) {
- // Filter allowed aspect ratios
- $cropVariant['allowedAspectRatios'] = array_filter(
- $cropVariant['allowedAspectRatios'] ?? [],
- static function ($aspectRatio) {
- return !(bool)($aspectRatio['disabled'] ?? false);
- }
- );
-
- // Ignore disabled crop variants
- if (!empty($cropVariant['disabled'])) {
- continue;
- }
-
- if (empty($cropVariant['allowedAspectRatios'])) {
- throw new InvalidConfigurationException(
- 'Crop variants configuration ' . $id . ' contains no allowed aspect ratios',
- 1620147893
- );
- }
-
- // Enforce a crop area (default is full image)
- if (empty($cropVariant['cropArea'])) {
- $cropVariant['cropArea'] = Area::createEmpty()->asArray();
- }
-
- $cropVariants[$id] = $cropVariant;
- }
-
- $config['cropVariants'] = $cropVariants;
-
- $config['allowedExtensions'] ??= $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
-
- return $config;
- }
-
- protected function processConfiguration(array $config, string &$elementValue, File $file): array
- {
- $cropVariantCollection = CropVariantCollection::create($elementValue, $config['cropVariants']);
- if (empty($config['readOnly']) && !empty($file->getProperty('width'))) {
- $cropVariantCollection = $cropVariantCollection->applyRatioRestrictionToSelectedCropArea($file);
- $elementValue = (string)$cropVariantCollection;
- }
- $config['cropVariants'] = $cropVariantCollection->asArray();
- $config['allowedExtensions'] = implode(
- ', ',
- GeneralUtility::trimExplode(',', $config['allowedExtensions'], true)
- );
- return $config;
- }
-}
diff --git a/composer.json b/composer.json
index 4aa554c..90c46be 100755
--- a/composer.json
+++ b/composer.json
@@ -7,7 +7,7 @@
}
},
"require": {
- "typo3/cms-core": "^12.4 || 12.4.x-dev || dev-main",
+ "typo3/cms-core": "^12.4 || 12.4.x-dev",
"typo3/cms-backend": "*",
"typo3/cms-extbase": "*",
diff --git a/ext_localconf.php b/ext_localconf.php
index 9b40451..5fd1db4 100755
--- a/ext_localconf.php
+++ b/ext_localconf.php
@@ -3,7 +3,6 @@
defined('TYPO3') or die('access denied');
use Evoweb\EwBase\Form\Element\PickColorFromImage;
-use Evoweb\EwBase\Form\Element\PickColorFromImagePre13;
use Evoweb\EwBase\Form\FormDataProvider\UsercentricsDatabaseEditRow;
use Evoweb\EwBase\Form\FormDataProvider\UsercentricsTcaInline;
use Evoweb\EwBase\Hooks\UsercentricsPostRenderHook;
@@ -22,11 +21,10 @@ call_user_func(function () {
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'][] =
UsercentricsPostRenderHook::class . '->executePostRenderHook';
- $versionPre13 = (GeneralUtility::makeInstance(Typo3Version::class))->getMajorVersion() < 13;
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1681197508] = [
'nodeName' => 'pick-color-from-image',
'priority' => '70',
- 'class' => $versionPre13 ? PickColorFromImagePre13::class : PickColorFromImage::class,
+ 'class' => PickColorFromImage::class,
];
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][BaseSiteDatabaseEditRow::class] = [