Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC Work with Symfony Request #510

Draft
wants to merge 1 commit into
base: 2
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Flysystem/FlysystemAssetStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ public function revoke($filename, $hash)
if ($granted) {
$session->set(self::GRANTS_SESSION, $granted);
} else {
$session->clear(self::GRANTS_SESSION);
$session->remove(self::GRANTS_SESSION);
}
}

Expand Down
42 changes: 9 additions & 33 deletions src/Upload.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Security;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
* Manages uploads via HTML forms processed by PHP,
Expand Down Expand Up @@ -54,10 +55,8 @@ class Upload extends Controller
/**
* Information about the temporary file produced
* by the PHP-runtime.
*
* @var array
*/
protected $tmpFile;
protected UploadedFile $tmpFile;

/**
* Replace an existing file rather than renaming the new one.
Expand Down Expand Up @@ -157,12 +156,9 @@ protected function getAssetStore()

/**
* Save an file passed from a form post into the AssetStore directly
*
* @param array $tmpFile Indexed array that PHP generated for every file it uploads.
* @param string|bool $folderPath Folder path relative to /assets
* @return array|false Either the tuple array, or false if the file could not be saved
*/
public function load($tmpFile, $folderPath = false)
public function load(UploadedFile $tmpFile, string|bool $folderPath = false): array|false
{
// Validate filename
$filename = $this->getValidFilename($tmpFile, $folderPath);
Expand All @@ -182,14 +178,10 @@ public function load($tmpFile, $folderPath = false)
* Save an file passed from a form post into this object.
* File names are filtered through {@link FileNameFilter}, see class documentation
* on how to influence this behaviour.
*
* @param array $tmpFile
* @param AssetContainer $file
* @param string|bool $folderPath
* @return bool True if the file was successfully saved into this record
* @throws Exception
*/
public function loadIntoFile($tmpFile, $file = null, $folderPath = false)
public function loadIntoFile(UploadedFile $tmpFile, AssetContainer $file = null, string|bool$folderPath = false): bool
{
$this->file = $file;

Expand All @@ -214,13 +206,8 @@ public function loadIntoFile($tmpFile, $file = null, $folderPath = false)

/**
* Assign this temporary file into the given destination
*
* @param array $tmpFile
* @param string $filename
* @param AssetContainer|AssetStore $container
* @return array
*/
protected function storeTempFile($tmpFile, $filename, $container)
protected function storeTempFile(UploadedFile $tmpFile, string $filename, AssetContainer|AssetStore $container): array
{
// Save file into backend
$conflictResolution = $this->replaceFile
Expand All @@ -230,25 +217,17 @@ protected function storeTempFile($tmpFile, $filename, $container)
'conflict' => $conflictResolution,
'visibility' => $this->getDefaultVisibility()
];
return $container->setFromLocalFile($tmpFile['tmp_name'], $filename, null, null, $config);
return $container->setFromLocalFile($tmpFile->getPathname(), $filename, null, null, $config);
}

/**
* Given a temporary file and upload path, validate the file and determine the
* value of the 'Filename' tuple that should be used to store this asset.
*
* @param array $tmpFile
* @param string $folderPath
* @return string|false Value of filename tuple, or false if invalid
*/
protected function getValidFilename($tmpFile, $folderPath = null)
protected function getValidFilename(UploadedFile $tmpFile, ?string $folderPath = null): string|false
{
if (!is_array($tmpFile)) {
throw new InvalidArgumentException(
"Upload::load() Not passed an array. Most likely, the form hasn't got the right enctype"
);
}

// Validate
$this->clearErrors();
$valid = $this->validate($tmpFile);
Expand All @@ -261,7 +240,7 @@ protected function getValidFilename($tmpFile, $folderPath = null)
$folderPath = $this->config()->uploads_folder;
}
$nameFilter = FileNameFilter::create();
$file = $nameFilter->filter($tmpFile['name']);
$file = $nameFilter->filter($tmpFile->getClientOriginalName());
$filename = basename($file ?? '');
if ($folderPath) {
$filename = File::join_paths($folderPath, $filename);
Expand Down Expand Up @@ -346,11 +325,8 @@ public function getReplaceFile()
* Is NOT connected to the {Validator} classes,
* please have a look at {FileField->validate()}
* for an example implementation of external validation.
*
* @param array $tmpFile
* @return boolean
*/
public function validate($tmpFile)
public function validate(UploadedFile $tmpFile): bool
{
$validator = $this->validator;
$validator->setTmpFile($tmpFile);
Expand Down
36 changes: 16 additions & 20 deletions src/Upload_Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injectable;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class Upload_Validator
{
Expand Down Expand Up @@ -34,10 +35,8 @@ class Upload_Validator
/**
* Information about the temporary file produced
* by the PHP-runtime.
*
* @var array
*/
protected $tmpFile;
protected UploadedFile $tmpFile;

protected $errors = [];

Expand Down Expand Up @@ -82,9 +81,8 @@ public function clearErrors()

/**
* Set information about temporary file produced by PHP.
* @param array $tmpFile
*/
public function setTmpFile($tmpFile)
public function setTmpFile(UploadedFile $tmpFile): void
{
$this->tmpFile = $tmpFile;
}
Expand Down Expand Up @@ -220,13 +218,13 @@ public function setAllowedExtensions($rules)
public function isValidSize()
{
// If file was blocked via PHP for being excessive size, shortcut here
switch ($this->tmpFile['error']) {
switch ($this->tmpFile->getError()) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
return false;
}
$maxSize = $this->getAllowedMaxFileSize($this->getFileExtension());
return (!$this->tmpFile['size'] || !$maxSize || (int)$this->tmpFile['size'] < $maxSize);
return (!$this->tmpFile->getSize() || !$maxSize || $this->tmpFile->getSize() < $maxSize);
}

/**
Expand All @@ -237,10 +235,10 @@ public function isValidSize()
public function isFileEmpty()
{
// Don't check file size for errors
if ($this->tmpFile['error'] !== UPLOAD_ERR_OK) {
if ($this->tmpFile->getError() !== UPLOAD_ERR_OK) {
return false;
}
return empty($this->tmpFile['size']);
return empty($this->tmpFile->getSize());
}

/**
Expand All @@ -257,14 +255,12 @@ public function isValidExtension()
/**
* Return the extension of the uploaded file, in lowercase
* Returns an empty string for files without an extension
*
* @return string
*/
public function getFileExtension()
public function getFileExtension(): string
{
$pathInfo = pathinfo($this->tmpFile['name'] ?? '');
if (isset($pathInfo['extension'])) {
return strtolower($pathInfo['extension'] ?? '');
$extension = $this->tmpFile->getClientOriginalExtension();
if ($extension) {
return strtolower($extension);
}

// Special case for files without extensions
Expand All @@ -281,7 +277,7 @@ public function getFileExtension()
public function validate()
{
// we don't validate for empty upload fields yet
if (empty($this->tmpFile['name'])) {
if (empty($this->tmpFile->getFilename())) {
return true;
}

Expand Down Expand Up @@ -338,18 +334,18 @@ public function validate()
public function isValidUpload()
{
// Check file upload
if (in_array($this->tmpFile['error'], [UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE])) {
if (in_array($this->tmpFile->getError(), [UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE])) {
return false;
}

// Note that some "max file size" errors leave "tmp_name" empty, so don't fail on this.
if (empty($this->tmpFile['tmp_name'])) {
if (empty($this->tmpFile->getPathname())) {
return true;
}

// Check if file is valid uploaded (with exception for unit testing)
$useUploadedFile = $this->config()->get('use_is_uploaded_file');
if ($useUploadedFile && !is_uploaded_file($this->tmpFile['tmp_name'] ?? '')) {
if ($useUploadedFile && !is_uploaded_file($this->tmpFile->getPathname() ?? '')) {
return false;
}

Expand All @@ -363,6 +359,6 @@ public function isValidUpload()
*/
public function isCompleteUpload()
{
return ($this->tmpFile['error'] !== UPLOAD_ERR_PARTIAL);
return ($this->tmpFile->getError() !== UPLOAD_ERR_PARTIAL);
}
}