diff --git a/doc/fields.rst b/doc/fields.rst index 26cdd0d3b5..f59fae39b0 100644 --- a/doc/fields.rst +++ b/doc/fields.rst @@ -1127,8 +1127,8 @@ the full address is only visible on the detail and edit pages:: [$local, $domain] = explode('@', $email, 2); $field->setFormattedValue(substr($local, 0, 1).'***@'.$domain); - } - } + } + } .. tip:: diff --git a/src/Field/Configurator/FileConfigurator.php b/src/Field/Configurator/FileConfigurator.php index 6abce8d773..5ffa96779c 100644 --- a/src/Field/Configurator/FileConfigurator.php +++ b/src/Field/Configurator/FileConfigurator.php @@ -130,11 +130,12 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c // Disable download_path for Flysystem (URLs are built via flysystem_url_prefix) $field->setFormTypeOption('download_path', null); } else { - $relativeUploadDir = u($relativeUploadDir)->trimStart(\DIRECTORY_SEPARATOR)->ensureEnd(\DIRECTORY_SEPARATOR)->toString(); - $isStreamWrapper = filter_var($relativeUploadDir, \FILTER_VALIDATE_URL); - if (false !== $isStreamWrapper) { - $absoluteUploadDir = $relativeUploadDir; + $isStreamWrapper = false !== filter_var($relativeUploadDir, \FILTER_VALIDATE_URL); + $isAbsolutePath = str_starts_with($relativeUploadDir, \DIRECTORY_SEPARATOR); + if ($isStreamWrapper || $isAbsolutePath) { + $absoluteUploadDir = u($relativeUploadDir)->ensureEnd(\DIRECTORY_SEPARATOR)->toString(); } else { + $relativeUploadDir = u($relativeUploadDir)->trimStart(\DIRECTORY_SEPARATOR)->ensureEnd(\DIRECTORY_SEPARATOR)->toString(); $absoluteUploadDir = u($relativeUploadDir)->ensureStart($this->projectDir.\DIRECTORY_SEPARATOR)->toString(); } $field->setFormTypeOption('upload_dir', $absoluteUploadDir); diff --git a/src/Field/Configurator/ImageConfigurator.php b/src/Field/Configurator/ImageConfigurator.php index 36ef8e85e9..dac9a760a9 100644 --- a/src/Field/Configurator/ImageConfigurator.php +++ b/src/Field/Configurator/ImageConfigurator.php @@ -120,11 +120,12 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c // Disable download_path for Flysystem (URLs are built via flysystem_url_prefix) $field->setFormTypeOption('download_path', null); } else { - $relativeUploadDir = u($relativeUploadDir)->trimStart(\DIRECTORY_SEPARATOR)->ensureEnd(\DIRECTORY_SEPARATOR)->toString(); - $isStreamWrapper = filter_var($relativeUploadDir, \FILTER_VALIDATE_URL); - if (false !== $isStreamWrapper) { - $absoluteUploadDir = $relativeUploadDir; + $isStreamWrapper = false !== filter_var($relativeUploadDir, \FILTER_VALIDATE_URL); + $isAbsolutePath = str_starts_with($relativeUploadDir, \DIRECTORY_SEPARATOR); + if ($isStreamWrapper || $isAbsolutePath) { + $absoluteUploadDir = u($relativeUploadDir)->ensureEnd(\DIRECTORY_SEPARATOR)->toString(); } else { + $relativeUploadDir = u($relativeUploadDir)->trimStart(\DIRECTORY_SEPARATOR)->ensureEnd(\DIRECTORY_SEPARATOR)->toString(); $absoluteUploadDir = u($relativeUploadDir)->ensureStart($this->projectDir.\DIRECTORY_SEPARATOR)->toString(); } $field->setFormTypeOption('upload_dir', $absoluteUploadDir); diff --git a/src/Field/FileField.php b/src/Field/FileField.php index ed705b3ad1..b13851a314 100644 --- a/src/Field/FileField.php +++ b/src/Field/FileField.php @@ -70,7 +70,8 @@ public function setBasePath(string $path): self } /** - * Relative to project's root directory (e.g. use 'public/uploads/' for `/public/uploads/`) + * Relative paths are resolved from the project's root directory (e.g. 'public/uploads/' for `/public/uploads/`). + * Absolute filesystem paths are also supported (e.g. '/mnt/data/uploads/'), and so are stream wrappers (e.g. 's3://bucket/path/'). * Default upload dir: `/public/uploads/files/`. */ public function setUploadDir(string $uploadDirPath): self diff --git a/src/Field/ImageField.php b/src/Field/ImageField.php index 81f8128efd..452ac4112e 100644 --- a/src/Field/ImageField.php +++ b/src/Field/ImageField.php @@ -73,7 +73,8 @@ public function setBasePath(string $path): self } /** - * Relative to project's root directory (e.g. use 'public/uploads/' for `/public/uploads/`) + * Relative paths are resolved from the project's root directory (e.g. 'public/uploads/' for `/public/uploads/`). + * Absolute filesystem paths are also supported (e.g. '/mnt/data/uploads/'), and so are stream wrappers (e.g. 's3://bucket/path/'). * Default upload dir: `/public/uploads/images/`. */ public function setUploadDir(string $uploadDirPath): self