<?php
/**
* FileUpload.php - This class handles HTTP file upload.
*
* @package jaxon-core
* @author Thierry Feuzeu <thierry.feuzeu@gmail.com>
* @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link https://github.com/jaxon-php/jaxon-core
*/
namespace Jaxon\Request\Support;
use Closure;
class FileUpload
{
use \Jaxon\Features\Validator;
use \Jaxon\Features\Translator;
/**
* A user defined function to transform uploaded file names
*
* @var Closure
*/
protected $cNameSanitizer = null;
/**
* Filter uploaded file name
*
* @param Closure $cNameSanitizer The closure which filters filenames
*
* @return void
*/
public function setNameSanitizer(Closure $cNameSanitizer)
{
$this->cNameSanitizer = $cNameSanitizer;
}
/**
* Check uploaded files
*
* @param array $aFiles The uploaded files
*
* @return void
* @throws \Jaxon\Exception\Error
*/
private function checkFiles(array $aFiles)
{
foreach($aFiles as $sVarName => $aVarFiles)
{
foreach($aVarFiles as $aFile)
{
// Verify upload result
if($aFile['error'] != 0)
{
throw new \Jaxon\Exception\Error($this->trans('errors.upload.failed', $aFile));
}
// Verify file validity (format, size)
if(!$this->validateUploadedFile($sVarName, $aFile))
{
throw new \Jaxon\Exception\Error($this->getValidatorMessage());
}
}
}
}
/**
* Get a file from upload entry
*
* @param string $sVarName The corresponding variable
* @param array $aVarFiles An entry in the PHP $_FILES array
* @param integer $nPosition The postion of the file to be processed
*
* @return null|array
*/
private function getUploadedFile($sVarName, array $aVarFiles, $nPosition)
{
if(!$aVarFiles['name'][$nPosition])
{
return null;
}
// Filename without the extension
$sFilename = pathinfo($aVarFiles['name'][$nPosition], PATHINFO_FILENAME);
if(($this->cNameSanitizer))
{
$sFilename = (string)call_user_func_array($this->cNameSanitizer, [$sFilename, $sVarName]);
}
return [
'name' => $aVarFiles['name'][$nPosition],
'type' => $aVarFiles['type'][$nPosition],
'tmp_name' => $aVarFiles['tmp_name'][$nPosition],
'error' => $aVarFiles['error'][$nPosition],
'size' => $aVarFiles['size'][$nPosition],
'filename' => $sFilename,
'extension' => pathinfo($aVarFiles['name'][$nPosition], PATHINFO_EXTENSION),
];
}
/**
* Read uploaded files info from HTTP request data
*
* @return array
*/
public function getUploadedFiles()
{
// Check validity of the uploaded files
$aUploadedFiles = [];
foreach($_FILES as $sVarName => $aVarFiles)
{
// If there is only one file, transform each entry into an array,
// so the same processing for multiple files can be applied.
if(!is_array($aVarFiles['name']))
{
$aVarFiles['name'] = [$aVarFiles['name']];
$aVarFiles['type'] = [$aVarFiles['type']];
$aVarFiles['tmp_name'] = [$aVarFiles['tmp_name']];
$aVarFiles['error'] = [$aVarFiles['error']];
$aVarFiles['size'] = [$aVarFiles['size']];
}
$nFileCount = count($aVarFiles['name']);
for($i = 0; $i < $nFileCount; $i++)
{
$aUploadedFile = $this->getUploadedFile($sVarName, $aVarFiles, $i);
if(is_array($aUploadedFile))
{
if(!array_key_exists($sVarName, $aUploadedFiles))
{
$aUploadedFiles[$sVarName] = [];
}
$aUploadedFiles[$sVarName][] = $aUploadedFile;
}
}
}
// Check uploaded files validity
$this->checkFiles($aUploadedFiles);
return $aUploadedFiles;
}
}
|