diff --git a/.gitignore b/.gitignore
index 747b70c..343d80a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,16 +1,16 @@
-# OS
-.DS_Store
-Thumbs.db
-
-# IDEs
-.buildpath
-.project
-.settings/
-.build/
-.external*/
-.idea/
-nbproject/
-
-# composer related
-vendor/
-composer.lock
+# OS
+.DS_Store
+Thumbs.db
+
+# IDEs
+.buildpath
+.project
+.settings/
+.build/
+.external*/
+.idea/
+nbproject/
+
+# composer related
+vendor/
+composer.lock
diff --git a/.travis.yml b/.travis.yml
index 8eb9daa..ed27399 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,18 +11,17 @@ php:
- "7.4"
- "7.3"
- "7.2"
- - "7.1"
env:
- - CONTAO_VERSION=~4.8.0
- - CONTAO_VERSION=~4.4.0
+ - CONTAO_VERSION='contao/core-bundle ~4.9.0'
+ - CONTAO_VERSION='contao/core-bundle ~4.10.0@dev'
# Exclude impossible Contao Version combinations.
matrix:
fast_finish: true
allow_failures:
- - php: "7.4"
- - env: CONTAO_VERSION=~4.8.0
+ - php: "7.4"
+ - env: CONTAO_VERSION='contao/core-bundle ~4.10.0@dev'
before_script:
- echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
diff --git a/composer.json b/composer.json
index 9a67b81..8bef536 100644
--- a/composer.json
+++ b/composer.json
@@ -26,16 +26,16 @@
"source":"https://github.com/contao-community-alliance/dc-general-contao-frontend"
},
"require": {
- "php":"^7.1",
- "contao-community-alliance/dc-general": "^2.1.3",
+ "php":"^7.2",
+ "contao-community-alliance/dc-general": "^2.2",
"contao-community-alliance/url-builder": "~1.1",
- "contao-community-alliance/translator": "^2.1",
- "contao/core-bundle": "^4.4",
- "symfony/event-dispatcher": "^3.3 || ^4.0"
+ "contao-community-alliance/translator": "^2.2",
+ "contao/core-bundle": "^4.9",
+ "symfony/event-dispatcher": "4.4.*"
},
"require-dev": {
- "contao/manager-plugin": "^2.1",
- "phpcq/all-tasks": "~1.1",
+ "contao/manager-plugin": "^2.8",
+ "phpcq/all-tasks": "~1.2",
"phpmd/phpmd": "~2.8.2"
},
"autoload": {
@@ -46,8 +46,8 @@
"extra":{
"contao-manager-plugin": "ContaoCommunityAlliance\\DcGeneral\\ContaoFrontend\\ContaoManager\\Plugin",
"branch-alias": {
- "dev-master": "2.1.x-dev",
- "dev-support/2.0": "2.0.x-dev"
+ "dev-support/2.1.x": "2.1.x-dev",
+ "dev-master": "2.2.x-dev"
}
},
"config": {
diff --git a/src/Resources/contao/config/config.php b/src/Resources/contao/config/config.php
new file mode 100644
index 0000000..a0d22c0
--- /dev/null
+++ b/src/Resources/contao/config/config.php
@@ -0,0 +1,23 @@
+
+ * @copyright 2016-2019 Contao Community Alliance.
+ * @license https://github.com/contao-community-alliance/dc-general-contao-frontend/blob/master/LICENSE LGPL-3.0-or-later
+ * @filesource
+ */
+
+use ContaoCommunityAlliance\DcGeneral\ContaoFrontend\Widgets\UploadOnSteroids;
+
+// Front end form widgets
+$GLOBALS['TL_FFL']['uploadOnSteroids'] = UploadOnSteroids::class;
diff --git a/src/Resources/contao/templates/widgets/form_upload-on-steroids.html5 b/src/Resources/contao/templates/widgets/form_upload-on-steroids.html5
new file mode 100644
index 0000000..9d13cca
--- /dev/null
+++ b/src/Resources/contao/templates/widgets/form_upload-on-steroids.html5
@@ -0,0 +1,55 @@
+
+extend('form_row'); ?>
+
+block('label'); ?>
+label): ?>
+
+
+
+files): ?>
+
+
+
+ files as $key => $file): ?>
+ -
+ showThumbnail): ?>
+
+
= $file->name ?>
+
+ = $file->name ?>
+
+
+
+
+
+
+
+
+endblock(); ?>
+
+block('field'); ?>
+ hasErrors()): ?>
+ = $this->getErrorAsString() ?>
+
+
+ getAttributes() ?>>
+endblock(); ?>
diff --git a/src/View/ActionHandler/CopyHandler.php b/src/View/ActionHandler/CopyHandler.php
index cef71a3..ee138f9 100644
--- a/src/View/ActionHandler/CopyHandler.php
+++ b/src/View/ActionHandler/CopyHandler.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general-contao-frontend.
*
- * (c) 2015-2018 Contao Community Alliance.
+ * (c) 2015-2022 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -12,13 +12,15 @@
*
* @package contao-community-alliance/dc-general-contao-frontend
* @author Richard Henkenjohann
- * @copyright 2015-2018 Contao Community Alliance.
+ * @author Ingolf Steinhardt
+ * @copyright 2015-2022 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general-contao-frontend/blob/master/LICENSE LGPL-3.0
* @filesource
*/
namespace ContaoCommunityAlliance\DcGeneral\ContaoFrontend\View\ActionHandler;
+use Contao\CoreBundle\Exception\PageNotFoundException;
use Contao\CoreBundle\Exception\RedirectResponseException;
use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator;
use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminatorAwareTrait;
@@ -122,7 +124,12 @@ public function process(EnvironmentInterface $environment): void
$dataProvider = $environment->getDataProvider();
$model = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId()));
- $copyModel = $environment->getController()->createClonedModel($model);
+
+ if (null === $model) {
+ throw new PageNotFoundException('Model not found: ' . $modelId->getSerialized());
+ }
+
+ $copyModel = $environment->getController()->createClonedModel($model);
// Dispatch pre duplicate event.
$copyEvent = new PreDuplicateModelEvent($environment, $copyModel, $model);
diff --git a/src/View/ActionHandler/DeleteHandler.php b/src/View/ActionHandler/DeleteHandler.php
index a26cce3..79e214e 100644
--- a/src/View/ActionHandler/DeleteHandler.php
+++ b/src/View/ActionHandler/DeleteHandler.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general-contao-frontend.
*
- * (c) 2015-2018 Contao Community Alliance.
+ * (c) 2015-2022 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -12,13 +12,15 @@
*
* @package contao-community-alliance/dc-general-contao-frontend
* @author Richard Henkenjohann
- * @copyright 2015-2018 Contao Community Alliance.
+ * @author Ingolf Steinhardt
+ * @copyright 2015-2022 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general-contao-frontend/blob/master/LICENSE LGPL-3.0
* @filesource
*/
namespace ContaoCommunityAlliance\DcGeneral\ContaoFrontend\View\ActionHandler;
+use Contao\CoreBundle\Exception\PageNotFoundException;
use Contao\CoreBundle\Exception\RedirectResponseException;
use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator;
use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminatorAwareTrait;
@@ -115,6 +117,10 @@ public function process(EnvironmentInterface $environment): void
$dataProvider = $environment->getDataProvider();
$model = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId()));
+ if (null === $model) {
+ throw new PageNotFoundException('Model not found: ' . $modelId->getSerialized());
+ }
+
// Trigger event before the model will be deleted.
$event = new PreDeleteModelEvent($environment, $model);
$environment->getEventDispatcher()->dispatch($event::NAME, $event);
diff --git a/src/View/ActionHandler/EditHandler.php b/src/View/ActionHandler/EditHandler.php
index 0c86e26..0527acc 100644
--- a/src/View/ActionHandler/EditHandler.php
+++ b/src/View/ActionHandler/EditHandler.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general-contao-frontend.
*
- * (c) 2015-2020 Contao Community Alliance.
+ * (c) 2015-2022 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,7 +14,8 @@
* @author Christian Schiffler
* @author Richard Henkenjohann
* @author Sven Baumann
- * @copyright 2015-2020 Contao Community Alliance.
+ * @author Ingolf Steinhardt
+ * @copyright 2015-2022 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general-contao-frontend/blob/master/LICENSE LGPL-3.0
* @filesource
*/
@@ -103,20 +104,23 @@ public function process(EnvironmentInterface $environment)
if (!$basicDefinition->isEditable()) {
throw new NotEditableException('DataContainer ' . $definition->getName() . ' is not editable');
}
+
// We only support flat tables, sorry.
if (BasicDefinitionInterface::MODE_HIERARCHICAL === $basicDefinition->getMode()) {
return false;
}
+
$modelId = ModelId::fromSerialized($environment->getInputProvider()->getParameter('id'));
$dataProvider = $environment->getDataProvider();
$model = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId()));
- $clone = clone $model;
if (null === $model) {
throw new PageNotFoundException('Model not found: ' . $modelId->getSerialized());
}
+ $clone = clone $model;
+
return (new EditMask($environment, $model, $clone, null, null))->execute();
}
}
diff --git a/src/View/EditMask.php b/src/View/EditMask.php
index d9863c2..f713d99 100644
--- a/src/View/EditMask.php
+++ b/src/View/EditMask.php
@@ -3,7 +3,7 @@
/**
* This file is part of contao-community-alliance/dc-general-contao-frontend.
*
- * (c) 2015-2018 Contao Community Alliance.
+ * (c) 2015-2020 Contao Community Alliance.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -13,7 +13,9 @@
* @package contao-community-alliance/dc-general-contao-frontend
* @author Christian Schiffler
* @author Richard Henkenjohann
- * @copyright 2015-2018 Contao Community Alliance.
+ * @author Sven Baumann
+ * @author Ingolf Steinhardt
+ * @copyright 2015-2020 Contao Community Alliance.
* @license https://github.com/contao-community-alliance/dc-general-contao-frontend/blob/master/LICENSE LGPL-3.0
* @filesource
*/
@@ -194,7 +196,8 @@ public function execute()
'table' => $this->definition->getName(),
'enctype' => 'multipart/form-data',
'error' => $this->errors,
- 'editButtons' => $buttons
+ 'editButtons' => $buttons,
+ 'model' => $this->model
]
);
@@ -315,17 +318,25 @@ private function translateLabel($transString, $parameters = [])
*/
private function getEditButtons()
{
+ $button = '';
$buttons = [];
$buttons['save'] = sprintf(
- '',
+ $button,
+ 'save',
+ 'save',
+ 'save',
+ 's',
$this->translateLabel('save')
);
if ($this->definition->getBasicDefinition()->isCreatable()) {
$buttons['saveNcreate'] = sprintf(
- '',
+ $button,
+ 'saveNcreate',
+ 'saveNcreate',
+ 'saveNcreate',
+ 'n',
$this->translateLabel('saveNcreate')
);
}
diff --git a/src/Widgets/UploadOnSteroids.php b/src/Widgets/UploadOnSteroids.php
new file mode 100644
index 0000000..36f9509
--- /dev/null
+++ b/src/Widgets/UploadOnSteroids.php
@@ -0,0 +1,623 @@
+
+ * @copyright 2016-2019 Contao Community Alliance.
+ * @license https://github.com/contao-community-alliance/dc-general-contao-frontend/blob/master/LICENSE
+ * LGPL-3.0-or-later
+ * @filesource
+ */
+
+namespace ContaoCommunityAlliance\DcGeneral\ContaoFrontend\Widgets;
+
+use Contao\CoreBundle\Framework\Adapter;
+use Contao\Dbafs;
+use Contao\FilesModel;
+use Contao\FormFileUpload;
+use Contao\Input;
+use Contao\StringUtil;
+use Doctrine\DBAL\Connection;
+use Symfony\Component\Filesystem\Filesystem;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * This is the widget is for upload a file in the frontend editing scope.
+ * It has the following functions:
+ * - Saves the uploaded file in the configured directory
+ * - Can be reset from the model
+ * - Can delete the file from disk space
+ * - Can add a default image
+ * - Can add a default image
+ * - Output the Image as Thumbnail
+ * - Normalize the extend folder (StringUtil::generateAlias)
+ * - Can prefix and postfix the filename.
+ *
+ * @property boolean deselect
+ * @property boolean delete
+ * @property string extendFolder
+ * @property boolean normalizeExtendFolder
+ * @property boolean normalizeFilename
+ * @property string prefixFilename
+ * @property string postfixFilename
+ * @property array files
+ * @property boolean showThumbnail
+ * @property boolean multiple
+ */
+class UploadOnSteroids extends FormFileUpload
+{
+ /**
+ * Submit indicator
+ *
+ * @var boolean
+ */
+ protected $blnSubmitInput = true;
+
+ /**
+ * Template
+ *
+ * @var string
+ */
+ protected $strTemplate = 'form_upload-on-steroids';
+
+ /**
+ * Template
+ *
+ * @var string
+ */
+ protected $strPrefix = 'widget widget-upload widget-upload-on-steroids';
+
+ /**
+ * The translator
+ *
+ * @var TranslatorInterface
+ */
+ protected $translator;
+
+ /**
+ * The input provider;
+ *
+ * @var Adapter|Input
+ */
+ protected $inputProvider;
+
+ /**
+ * The file model.
+ *
+ * @var Adapter|FilesModel
+ */
+ private $filesModel;
+
+ /**
+ * The filesystem.
+ *
+ * @var Filesystem
+ */
+ private $filesystem;
+ /**
+ * The string util.
+ *
+ * @var StringUtil
+ */
+ private $stringUtil;
+
+ public function __construct($attributes = null)
+ {
+ parent::__construct($attributes);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function __set($key, $value)
+ {
+ if (\in_array(
+ $key,
+ [
+ 'deselect',
+ 'delete',
+ 'extendFolder',
+ 'normalizeExtendFolder',
+ 'normalizeFilename',
+ 'prefixFilename',
+ 'postfixFilename',
+ 'files',
+ 'showThumbnail',
+ 'multiple'
+ ]
+ )) {
+ $this->arrConfiguration[$key] = $value;
+
+ return;
+ }
+
+ parent::__set($key, $value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function parse($attributes = null)
+ {
+ $this->addIsDeletable();
+ $this->addIsDeselectable();
+ $this->addIsMultiple();
+ $this->addShowThumbnail();
+ $this->addFiles();
+
+ $this->value = \implode(',', \array_map('\Contao\StringUtil::binToUuid', (array) $this->value));
+
+ return parent::parse($attributes);
+ }
+
+ /**
+ * Parse the filename.
+ *
+ * @param string $filename The filename.
+ *
+ * @return string
+ */
+ public function parseFilename(string $filename): string
+ {
+ if (empty($filename) || !\is_string($filename)) {
+ return $filename;
+ }
+
+ return $this->normalizeFilename($this->preOrPostFixFilename($filename));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function validate()
+ {
+ $inputName = $this->name;
+
+ if ($this->normalizeExtendFolder) {
+ $this->extendFolder = $this->str()->generateAlias($this->extendFolder);
+ }
+
+ if ($this->extendFolder) {
+ $uploadFolder = $this->filesModel()->findByUuid($this->uploadFolder);
+ $uploadFolderPath = $uploadFolder->path . DIRECTORY_SEPARATOR . $this->extendFolder;
+
+
+ $newUploadFolder = null;
+ if (!$this->filesystem()->exists($uploadFolderPath)) {
+ $this->filesystem()->mkdir($uploadFolderPath);
+ $newUploadFolder = Dbafs::addResource($uploadFolderPath);
+ }
+
+ if (!$newUploadFolder) {
+ $newUploadFolder = $this->filesModel()->findByPath($uploadFolderPath);
+ }
+
+ $this->uploadFolder = $newUploadFolder->uuid;
+ }
+
+ $this->validateSingleUpload();
+ $this->validateMultipleUpload();
+ $this->deselectFile($inputName);
+ $this->deleteFile($inputName);
+ }
+
+ /**
+ * Validate single upload widget.
+ *
+ * @return void
+ */
+ private function validateSingleUpload(): void
+ {
+ if ($this->multiple || $this->hasErrors()) {
+ return;
+ }
+
+ $inputName = $this->name;
+ $_FILES[$inputName]['name'] = $this->parseFilename($_FILES[$inputName]['name']);
+
+ parent::validate();
+
+ if (!isset($_SESSION['FILES'][$inputName]) || $this->hasErrors()) {
+ return;
+ }
+
+ $file = $_SESSION['FILES'][$inputName];
+ if (!isset($file['uuid'])) {
+ return;
+ }
+
+ $this->value = StringUtil::uuidToBin($file['uuid']);
+ }
+
+ /**
+ * Validate multiple upload widget.
+ *
+ * @return void
+ */
+ private function validateMultipleUpload(): void
+ {
+ if (!$this->multiple || $this->hasErrors()) {
+ return;
+ }
+
+ $inputName = $this->name;
+ $values = \array_map('\Contao\StringUtil::binToUuid', $this->value);
+
+ $files = [];
+ $inputFiles = $this->getMultipleUploadedFiles();
+ foreach ($inputFiles as $inputFile) {
+ $_FILES[$inputName] = $inputFile;
+
+ $_FILES[$inputName]['name'] = $this->parseFilename($_FILES[$inputName]['name']);
+
+ parent::validate();
+
+ if (!isset($_SESSION['FILES'][$inputName]) || $this->hasErrors()) {
+ return;
+ }
+
+ $file = $_SESSION['FILES'][$inputName];
+ if (!isset($file['uuid'])) {
+ return;
+ }
+
+ $files[] = $file;
+
+ unset($_SESSION['FILES']);
+ }
+
+ if (!\count($files)) {
+ return;
+ }
+
+ $setValues = \array_values(\array_unique(\array_merge($values, \array_column($files, 'uuid'))));
+
+ $this->value = \array_map('\Contao\StringUtil::uuidToBin', $setValues);
+ }
+
+ /**
+ * Get the multiple uploaded files.
+ *
+ * @return array
+ */
+ private function getMultipleUploadedFiles(): array
+ {
+ if (!isset($_FILES[$this->name])) {
+ return [];
+ }
+
+ $files = [];
+ foreach ($_FILES[$this->name] as $propertyName => $values) {
+ foreach ($values as $key => $value) {
+ $files[$key][$propertyName] = $value;
+ }
+ }
+
+ return $files;
+ }
+
+ /**
+ * Deselect the file, if is mark for deselect.
+ *
+ * @param string $inputName The input nanme.
+ *
+ * @return void
+ */
+ private function deselectFile(string $inputName)
+ {
+ if (!$this->deselect
+ || $this->hasErrors()
+ || !($post = $this->inputProvider()->post($inputName))
+ || !isset($post['reset'][0])
+ ) {
+ return;
+ }
+
+ if (!$this->multiple && (StringUtil::binToUuid($this->value) === $post['reset'][0])) {
+ $this->value = '';
+
+ return;
+ }
+
+ $values = \array_map('\Contao\StringUtil::binToUuid', $this->value);
+ $diffValues = \array_values(\array_diff($values, $post['reset']));
+
+ $this->value = \array_map('\Contao\StringUtil::uuidToBin', $diffValues);
+ }
+
+ /**
+ * Delete the file, if is mark for delete.
+ *
+ * @param string $inputName The input nanme.
+ *
+ * @return void
+ */
+ private function deleteFile(string $inputName)
+ {
+ if (!$this->delete
+ || $this->hasErrors()
+ || !($post = $this->inputProvider()->post($inputName))
+ || !isset($post['delete'][0])
+ ) {
+ return;
+ }
+
+ if (!$this->multiple && (StringUtil::binToUuid($this->value) === $post['delete'][0])) {
+ $this->value = '';
+
+ $file = $this->filesModel()->findByUuid($this->value);
+ if ($file) {
+ $this->filesystem->remove($file->path);
+ $file->delete();
+ }
+
+ return;
+ }
+
+ $values = \array_map('\Contao\StringUtil::binToUuid', $this->value);
+ $diffValues = \array_values(\array_diff($values, $post['delete']));
+
+ foreach ($post['delete'] as $delete) {
+ $file = $this->filesModel()->findByUuid(StringUtil::uuidToBin($delete));
+ if (!$file) {
+ continue;
+ }
+
+ $this->filesystem()->remove($file->path);
+ $file->delete();
+ }
+
+ $this->value = \array_map('\Contao\StringUtil::uuidToBin', $diffValues);
+ }
+
+ /**
+ * Normalize the filename.
+ *
+ * @param array $file The file information.
+ *
+ * @return void
+ */
+ /**
+ * Normalize the filename.
+ *
+ * @param string $filename The filename.
+ *
+ * @return string
+ */
+ private function normalizeFilename(string $filename): string
+ {
+ if (!$this->normalizeFilename) {
+ return $filename;
+ }
+
+ $fileInfo = \pathinfo($filename);
+
+ $currentExtension = $fileInfo['extension'];
+ $normalizeExtension = $this->stringUtil()->generateAlias($currentExtension);
+
+ $currentFilename = $fileInfo['filename'];
+ $normalizeFilename = $this->stringUtil()->generateAlias($currentFilename);
+
+ return $normalizeFilename . '.' . $normalizeExtension;
+ }
+
+ /**
+ * Prefix or postfix the filename.
+ *
+ * @param string $filename The filename
+ *
+ * @return string
+ */
+ private function preOrPostFixFilename(string $filename): string
+ {
+ if (!($this->prefixFilename || $this->postfixFilename)) {
+ return $filename;
+ }
+
+ $fileInfo = \pathinfo($filename);
+
+ $extension = $fileInfo['extension'];
+
+ $currentFilename = $fileInfo['filename'];
+ $extendFilename = ($this->prefixFilename ?: '') .
+ 'place-holder-extend-filename' .
+ ($this->postfixFilename ?: '');
+ if ($this->normalizeFilename) {
+ $extendFilename = $this->stringUtil()->generateAlias($extendFilename);
+ }
+ $extendFilename = \str_replace('place-holder-extend-filename', $currentFilename, $extendFilename);
+
+ return $extendFilename . '.' . $extension;
+ }
+
+ /**
+ * Add the files from the value.
+ *
+ * @return void
+ */
+ private function addFiles(): void
+ {
+ if (empty($this->value)) {
+ $this->files = null;
+ return;
+ }
+
+ /** @var Connection $connection */
+ $connection = self::getContainer()->get('database_connection');
+
+ $platform = $connection->getDatabasePlatform();
+
+ $builder = $connection->createQueryBuilder();
+ $builder
+ ->select(
+ $platform->quoteIdentifier('id'),
+ $platform->quoteIdentifier('pid'),
+ $platform->quoteIdentifier('uuid'),
+ $platform->quoteIdentifier('type'),
+ $platform->quoteIdentifier('path'),
+ $platform->quoteIdentifier('extension'),
+ $platform->quoteIdentifier('hash'),
+ $platform->quoteIdentifier('found'),
+ $platform->quoteIdentifier('name'),
+ $platform->quoteIdentifier('importantPartX'),
+ $platform->quoteIdentifier('importantPartY'),
+ $platform->quoteIdentifier('importantPartWidth'),
+ $platform->quoteIdentifier('importantPartHeight'),
+ $platform->quoteIdentifier('meta')
+ )
+ ->from($platform->quoteIdentifier('tl_files'))
+ ->where($builder->expr()->in($platform->quoteIdentifier('uuid'), ':uuids'))
+ ->setParameter(':uuids', (array) $this->value, Connection::PARAM_STR_ARRAY);
+
+ $statement = $builder->execute();
+ if (!$statement->rowCount()) {
+ return;
+ }
+
+ $this->files = $statement->fetchAll(\PDO::FETCH_OBJ);
+ }
+
+ /**
+ * Translate.
+ *
+ * @param string $transId The message id (may also be an object that can be cast to string)
+ * @param array $parameters An array of parameters for the message
+ * @param string|null $domain The domain for the message or null to use the default
+ * @param string|null $locale The locale or null to use the default
+ *
+ * @return string
+ */
+ public function trans(
+ string $transId,
+ array $parameters = [],
+ ?string $domain = 'contao_default',
+ ?string $locale = null
+ ) {
+ return $this->translator()->trans($transId, $parameters, $domain, $locale);
+ }
+
+ /**
+ * Add file is deletable.
+ *
+ * @return void
+ */
+ private function addIsDeletable(): void
+ {
+ $this->prefix .= $this->delete ? ' is-deletable' : '';
+ }
+
+ /**
+ * Add file is deselectable.
+ *
+ * @return void
+ */
+ private function addIsDeselectable(): void
+ {
+ $this->prefix .= $this->deselect ? ' is-deselectable' : '';
+ }
+
+ /**
+ * Add file show thumbnail.
+ *
+ * @return void
+ */
+ private function addShowThumbnail(): void
+ {
+ $this->prefix .= $this->showThumbnail ? ' show-thumbnail' : '';
+ }
+
+ /**
+ * Add the upload file is multiple.
+ *
+ * @return void
+ */
+ private function addIsMultiple(): void
+ {
+ if (!$this->multiple) {
+ return;
+ }
+
+ $this->prefix .= $this->multiple ? ' is-multiple' : '';
+
+ $this->addAttribute('multiple', 'multiple');
+ }
+
+ /**
+ * Get the input provider.
+ *
+ * @return Adapter|Input
+ */
+ private function inputProvider(): Adapter
+ {
+ if (!$this->inputProvider) {
+ $this->inputProvider = self::getContainer()->get('contao.framework')->getAdapter(Input::class);
+ }
+
+ return $this->inputProvider;
+ }
+
+ /**
+ * Get the files model.
+ *
+ * @return Adapter|FilesModel
+ */
+ private function filesModel(): Adapter
+ {
+ if (!$this->filesModel) {
+ $this->filesModel = self::getContainer()->get('contao.framework')->getAdapter(FilesModel::class);
+ }
+
+ return $this->filesModel;
+ }
+
+ /**
+ * Get the filesystem.
+ *
+ * @return Filesystem
+ */
+ private function filesystem(): Filesystem
+ {
+ if (!$this->filesystem) {
+ $this->filesystem = self::getContainer()->get('filesystem');
+ }
+
+ return $this->filesystem;
+ }
+
+ /**
+ * Get the string util.
+ *
+ * @return Adapter|StringUtil
+ */
+ private function stringUtil(): Adapter
+ {
+ if (!$this->stringUtil) {
+ $this->stringUtil = self::getContainer()->get('contao.framework')->getAdapter(StringUtil::class);
+ }
+
+ return $this->stringUtil;
+ }
+
+ /**
+ * Get the translator.
+ *
+ * @return TranslatorInterface
+ */
+ private function translator(): TranslatorInterface
+ {
+ if (!$this->filesystem) {
+ $this->filesystem = self::getContainer()->get('translator');
+ }
+
+ return $this->filesystem;
+ }
+}