Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1505 lines (1314 sloc) 44.097 kb
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\File\Transfer\Adapter;
use ErrorException;
use Zend\File\Transfer;
use Zend\File\Transfer\Exception;
use Zend\Filter;
use Zend\Filter\Exception as FilterException;
use Zend\I18n\Translator\Translator;
use Zend\I18n\Translator\TranslatorAwareInterface;
use Zend\Stdlib\ErrorHandler;
use Zend\Validator;
/**
* Abstract class for file transfers (Downloads and Uploads)
*
* This class needs a full rewrite. It re-implements functionality present in
* Zend\Filter\Input and/or Zend\Form\Element, and in a way that's inconsistent
* with either one. Additionally, plugin loader usage is now deprecated -- but
* modifying that should be done in tandem with a rewrite to utilize validator
* and filter chains instead.
*
* @todo Rewrite
*/
abstract class AbstractAdapter implements TranslatorAwareInterface
{
/**@+
* Plugin loader Constants
*/
const FILTER = 'FILTER';
const VALIDATOR = 'VALIDATOR';
/**@-*/
/**
* Internal list of breaks
*
* @var array
*/
protected $break = array();
/**
* @var FilterPluginManager
*/
protected $filterManager;
/**
* Internal list of filters
*
* @var array
*/
protected $filters = array();
/**
* Plugin loaders for filter and validation chains
*
* @var array
*/
protected $loaders = array();
/**
* Internal list of messages
*
* @var array
*/
protected $messages = array();
/**
* @var Translator
*/
protected $translator;
/**
* Is translation enabled?
*
* @var bool
*/
protected $translatorEnabled = true;
/**
* Translator text domain (optional)
*
* @var string
*/
protected $translatorTextDomain = 'default';
/**
* @var ValidatorPluginManager
*/
protected $validatorManager;
/**
* Internal list of validators
* @var array
*/
protected $validators = array();
/**
* Internal list of files
* This array looks like this:
* array(form => array( - Form is the name within the form or, if not set the filename
* name, - Original name of this file
* type, - Mime type of this file
* size, - Filesize in bytes
* tmp_name, - Internally temporary filename for uploaded files
* error, - Error which has occurred
* destination, - New destination for this file
* validators, - Set validator names for this file
* files - Set file names for this file
* ))
*
* @var array
*/
protected $files = array();
/**
* TMP directory
* @var string
*/
protected $tmpDir;
/**
* Available options for file transfers
*/
protected $options = array(
'ignoreNoFile' => false,
'useByteString' => true,
'magicFile' => null,
'detectInfos' => true,
);
/**
* Send file
*
* @param mixed $options
* @return bool
*/
abstract public function send($options = null);
/**
* Receive file
*
* @param mixed $options
* @return bool
*/
abstract public function receive($options = null);
/**
* Is file sent?
*
* @param array|string|null $files
* @return bool
*/
abstract public function isSent($files = null);
/**
* Is file received?
*
* @param array|string|null $files
* @return bool
*/
abstract public function isReceived($files = null);
/**
* Has a file been uploaded ?
*
* @param array|string|null $files
* @return bool
*/
abstract public function isUploaded($files = null);
/**
* Has the file been filtered ?
*
* @param array|string|null $files
* @return bool
*/
abstract public function isFiltered($files = null);
/**
* Adds one or more files
*
* @param string|array $file File to add
* @param string|array $validator Validators to use for this file, must be set before
* @param string|array $filter Filters to use for this file, must be set before
* @return AbstractAdapter
* @throws Exception Not implemented
*/
//abstract public function addFile($file, $validator = null, $filter = null);
/**
* Returns all set types
*
* @return array List of set types
* @throws Exception Not implemented
*/
//abstract public function getType();
/**
* Adds one or more type of files
*
* @param string|array $type Type of files to add
* @param string|array $validator Validators to use for this file, must be set before
* @param string|array $filter Filters to use for this file, must be set before
* @return AbstractAdapter
* @throws Exception Not implemented
*/
//abstract public function addType($type, $validator = null, $filter = null);
/**
* Returns all set files
*
* @return array List of set files
*/
//abstract public function getFile();
/**
* Set the filter plugin manager instance
*
* @param FilterPluginManager $filterManager
* @return AbstractAdapter
*/
public function setFilterManager(FilterPluginManager $filterManager)
{
$this->filterManager = $filterManager;
return $this;
}
/**
* Get the filter plugin manager instance
*
* @return FilterPluginManager
*/
public function getFilterManager()
{
if (!$this->filterManager instanceof FilterPluginManager) {
$this->setFilterManager(new FilterPluginManager());
}
return $this->filterManager;
}
/**
* Set the validator plugin manager instance
*
* @param ValidatorPluginManager $validatorManager
* @return AbstractAdapter
*/
public function setValidatorManager(ValidatorPluginManager $validatorManager)
{
$this->validatorManager = $validatorManager;
return $this;
}
/**
* Get the validator plugin manager instance
*
* @return ValidatorPluginManager
*/
public function getValidatorManager()
{
if (!$this->validatorManager instanceof ValidatorPluginManager) {
$this->setValidatorManager(new ValidatorPluginManager());
}
return $this->validatorManager;
}
/**
* Adds a new validator for this class
*
* @param string|Validator\ValidatorInterface $validator Type of validator to add
* @param bool $breakChainOnFailure If the validation chain should stop an failure
* @param string|array $options Options to set for the validator
* @param string|array $files Files to limit this validator to
* @return AbstractAdapter
* @throws Exception\InvalidArgumentException for invalid type
*/
public function addValidator($validator, $breakChainOnFailure = false, $options = null, $files = null)
{
if (is_string($validator)) {
$validator = $this->getValidatorManager()->get($validator, $options);
if (is_array($options) && isset($options['messages'])) {
if (is_array($options['messages'])) {
$validator->setMessages($options['messages']);
} elseif (is_string($options['messages'])) {
$validator->setMessage($options['messages']);
}
unset($options['messages']);
}
}
if (!$validator instanceof Validator\ValidatorInterface) {
throw new Exception\InvalidArgumentException(
'Invalid validator provided to addValidator; ' .
'must be string or Zend\Validator\ValidatorInterface'
);
}
$name = get_class($validator);
$this->validators[$name] = $validator;
$this->break[$name] = $breakChainOnFailure;
$files = $this->getFiles($files, true, true);
foreach ($files as $file) {
if ($name == 'NotEmpty') {
$temp = $this->files[$file]['validators'];
$this->files[$file]['validators'] = array($name);
$this->files[$file]['validators'] += $temp;
} else {
$this->files[$file]['validators'][] = $name;
}
$this->files[$file]['validated'] = false;
}
return $this;
}
/**
* Add Multiple validators at once
*
* @param array $validators
* @param string|array $files
* @return AbstractAdapter
* @throws Exception\InvalidArgumentException for invalid type
*/
public function addValidators(array $validators, $files = null)
{
foreach ($validators as $name => $validatorInfo) {
if ($validatorInfo instanceof Validator\ValidatorInterface) {
$this->addValidator($validatorInfo, null, null, $files);
} elseif (is_string($validatorInfo)) {
if (!is_int($name)) {
$this->addValidator($name, null, $validatorInfo, $files);
} else {
$this->addValidator($validatorInfo, null, null, $files);
}
} elseif (is_array($validatorInfo)) {
$argc = count($validatorInfo);
$breakChainOnFailure = false;
$options = array();
if (isset($validatorInfo['validator'])) {
$validator = $validatorInfo['validator'];
if (isset($validatorInfo['breakChainOnFailure'])) {
$breakChainOnFailure = $validatorInfo['breakChainOnFailure'];
}
if (isset($validatorInfo['options'])) {
$options = $validatorInfo['options'];
}
$this->addValidator($validator, $breakChainOnFailure, $options, $files);
} else {
if (is_string($name)) {
$validator = $name;
$options = $validatorInfo;
$this->addValidator($validator, $breakChainOnFailure, $options, $files);
} else {
$file = $files;
switch (true) {
case (0 == $argc):
break;
case (1 <= $argc):
$validator = array_shift($validatorInfo);
case (2 <= $argc):
$breakChainOnFailure = array_shift($validatorInfo);
case (3 <= $argc):
$options = array_shift($validatorInfo);
case (4 <= $argc):
if (!empty($validatorInfo)) {
$file = array_shift($validatorInfo);
}
default:
$this->addValidator($validator, $breakChainOnFailure, $options, $file);
break;
}
}
}
} else {
throw new Exception\InvalidArgumentException('Invalid validator passed to addValidators()');
}
}
return $this;
}
/**
* Sets a validator for the class, erasing all previous set
*
* @param array $validators Validators to set
* @param string|array $files Files to limit this validator to
* @return AbstractAdapter
*/
public function setValidators(array $validators, $files = null)
{
$this->clearValidators();
return $this->addValidators($validators, $files);
}
/**
* Determine if a given validator has already been registered
*
* @param string $name
* @return bool
*/
public function hasValidator($name)
{
return (false !== $this->getValidatorIdentifier($name));
}
/**
* Retrieve individual validator
*
* @param string $name
* @return Validator\ValidatorInterface|null
*/
public function getValidator($name)
{
if (false === ($identifier = $this->getValidatorIdentifier($name))) {
return null;
}
return $this->validators[$identifier];
}
/**
* Returns all set validators
*
* @param string|array $files (Optional) Returns the validator for this files
* @return null|array List of set validators
*/
public function getValidators($files = null)
{
if ($files == null) {
return $this->validators;
}
$files = $this->getFiles($files, true, true);
$validators = array();
foreach ($files as $file) {
if (!empty($this->files[$file]['validators'])) {
$validators += $this->files[$file]['validators'];
}
}
$validators = array_unique($validators);
$result = array();
foreach ($validators as $validator) {
$result[$validator] = $this->validators[$validator];
}
return $result;
}
/**
* Remove an individual validator
*
* @param string $name
* @return AbstractAdapter
*/
public function removeValidator($name)
{
if (false === ($key = $this->getValidatorIdentifier($name))) {
return $this;
}
unset($this->validators[$key]);
foreach (array_keys($this->files) as $file) {
if (empty($this->files[$file]['validators'])) {
continue;
}
$index = array_search($key, $this->files[$file]['validators']);
if ($index === false) {
continue;
}
unset($this->files[$file]['validators'][$index]);
$this->files[$file]['validated'] = false;
}
return $this;
}
/**
* Remove all validators
*
* @return AbstractAdapter
*/
public function clearValidators()
{
$this->validators = array();
foreach (array_keys($this->files) as $file) {
$this->files[$file]['validators'] = array();
$this->files[$file]['validated'] = false;
}
return $this;
}
/**
* Sets Options for adapters
*
* @param array $options Options to set
* @param array $files (Optional) Files to set the options for
* @return AbstractAdapter
*/
public function setOptions($options = array(), $files = null)
{
$file = $this->getFiles($files, false, true);
if (is_array($options)) {
if (empty($file)) {
$this->options = array_merge($this->options, $options);
}
foreach ($options as $name => $value) {
foreach ($file as $key => $content) {
switch ($name) {
case 'magicFile' :
$this->files[$key]['options'][$name] = (string) $value;
break;
case 'ignoreNoFile' :
case 'useByteString' :
case 'detectInfos' :
$this->files[$key]['options'][$name] = (bool) $value;
break;
default:
continue;
}
}
}
}
return $this;
}
/**
* Returns set options for adapters or files
*
* @param array $files (Optional) Files to return the options for
* @return array Options for given files
*/
public function getOptions($files = null)
{
$file = $this->getFiles($files, false, true);
foreach ($file as $key => $content) {
if (isset($this->files[$key]['options'])) {
$options[$key] = $this->files[$key]['options'];
} else {
$options[$key] = array();
}
}
return $options;
}
/**
* Checks if the files are valid
*
* @param string|array $files (Optional) Files to check
* @return bool True if all checks are valid
*/
public function isValid($files = null)
{
$check = $this->getFiles($files, false, true);
if (empty($check)) {
return false;
}
$translator = $this->getTranslator();
$this->messages = array();
$break = false;
foreach ($check as $content) {
if (array_key_exists('validators', $content) &&
in_array('Zend\Validator\File\Count', $content['validators'])) {
$validator = $this->validators['Zend\Validator\File\Count'];
$count = $content;
if (empty($content['tmp_name'])) {
continue;
}
if (array_key_exists('destination', $content)) {
$checkit = $content['destination'];
} else {
$checkit = dirname($content['tmp_name']);
}
$checkit .= DIRECTORY_SEPARATOR . $content['name'];
$validator->addFile($checkit);
}
}
if (isset($count)) {
if (!$validator->isValid($count['tmp_name'], $count)) {
$this->messages += $validator->getMessages();
}
}
foreach ($check as $key => $content) {
$fileerrors = array();
if (array_key_exists('validators', $content) && $content['validated']) {
continue;
}
if (array_key_exists('validators', $content)) {
foreach ($content['validators'] as $class) {
$validator = $this->validators[$class];
if (method_exists($validator, 'setTranslator')) {
$validator->setTranslator($translator);
}
if (($class === 'Zend\Validator\File\Upload') && (empty($content['tmp_name']))) {
$tocheck = $key;
} else {
$tocheck = $content['tmp_name'];
}
if (!$validator->isValid($tocheck, $content)) {
$fileerrors += $validator->getMessages();
}
if (!empty($content['options']['ignoreNoFile']) && (isset($fileerrors['fileUploadErrorNoFile']))) {
unset($fileerrors['fileUploadErrorNoFile']);
break;
}
if (($class === 'Zend\Validator\File\Upload') && (count($fileerrors) > 0)) {
break;
}
if (($this->break[$class]) && (count($fileerrors) > 0)) {
$break = true;
break;
}
}
}
if (count($fileerrors) > 0) {
$this->files[$key]['validated'] = false;
} else {
$this->files[$key]['validated'] = true;
}
$this->messages += $fileerrors;
if ($break) {
break;
}
}
if (count($this->messages) > 0) {
return false;
}
return true;
}
/**
* Returns found validation messages
*
* @return array
*/
public function getMessages()
{
return $this->messages;
}
/**
* Retrieve error codes
*
* @return array
*/
public function getErrors()
{
return array_keys($this->messages);
}
/**
* Are there errors registered?
*
* @return bool
*/
public function hasErrors()
{
return (!empty($this->messages));
}
/**
* Adds a new filter for this class
*
* @param string|Filter\FilterInterface $filter Type of filter to add
* @param string|array $options Options to set for the filter
* @param string|array $files Files to limit this filter to
* @return AbstractAdapter
* @throws Exception\InvalidArgumentException for invalid type
*/
public function addFilter($filter, $options = null, $files = null)
{
if (is_string($filter)) {
$filter = $this->getFilterManager()->get($filter, $options);
}
if (!$filter instanceof Filter\FilterInterface) {
throw new Exception\InvalidArgumentException('Invalid filter specified');
}
$class = get_class($filter);
$this->filters[$class] = $filter;
$files = $this->getFiles($files, true, true);
foreach ($files as $file) {
$this->files[$file]['filters'][] = $class;
}
return $this;
}
/**
* Add Multiple filters at once
*
* @param array $filters
* @param string|array $files
* @return AbstractAdapter
*/
public function addFilters(array $filters, $files = null)
{
foreach ($filters as $key => $spec) {
if ($spec instanceof Filter\FilterInterface) {
$this->addFilter($spec, null, $files);
continue;
}
if (is_string($key)) {
$this->addFilter($key, $spec, $files);
continue;
}
if (is_int($key)) {
if (is_string($spec)) {
$this->addFilter($spec, null, $files);
continue;
}
if (is_array($spec)) {
if (!array_key_exists('filter', $spec)) {
continue;
}
$filter = $spec['filter'];
unset($spec['filter']);
$this->addFilter($filter, $spec, $files);
continue;
}
continue;
}
}
return $this;
}
/**
* Sets a filter for the class, erasing all previous set
*
* @param array $filters Filter to set
* @param string|array $files Files to limit this filter to
* @return Filter\AbstractFilter
*/
public function setFilters(array $filters, $files = null)
{
$this->clearFilters();
return $this->addFilters($filters, $files);
}
/**
* Determine if a given filter has already been registered
*
* @param string $name
* @return bool
*/
public function hasFilter($name)
{
return (false !== $this->getFilterIdentifier($name));
}
/**
* Retrieve individual filter
*
* @param string $name
* @return Filter\FilterInterface|null
*/
public function getFilter($name)
{
if (false === ($identifier = $this->getFilterIdentifier($name))) {
return null;
}
return $this->filters[$identifier];
}
/**
* Returns all set filters
*
* @param string|array $files (Optional) Returns the filter for this files
* @return array List of set filters
* @throws Exception\RuntimeException When file not found
*/
public function getFilters($files = null)
{
if ($files === null) {
return $this->filters;
}
$files = $this->getFiles($files, true, true);
$filters = array();
foreach ($files as $file) {
if (!empty($this->files[$file]['filters'])) {
$filters += $this->files[$file]['filters'];
}
}
$filters = array_unique($filters);
$result = array();
foreach ($filters as $filter) {
$result[] = $this->filters[$filter];
}
return $result;
}
/**
* Remove an individual filter
*
* @param string $name
* @return AbstractAdapter
*/
public function removeFilter($name)
{
if (false === ($key = $this->getFilterIdentifier($name))) {
return $this;
}
unset($this->filters[$key]);
foreach (array_keys($this->files) as $file) {
if (empty($this->files[$file]['filters'])) {
continue;
}
$index = array_search($key, $this->files[$file]['filters']);
if ($index === false) {
continue;
}
unset($this->files[$file]['filters'][$index]);
}
return $this;
}
/**
* Remove all filters
*
* @return AbstractAdapter
*/
public function clearFilters()
{
$this->filters = array();
foreach (array_keys($this->files) as $file) {
$this->files[$file]['filters'] = array();
}
return $this;
}
/**
* Retrieves the filename of transferred files.
*
* @param string $file (Optional) Element to return the filename for
* @param bool $path (Optional) Should the path also be returned ?
* @return string|array
*/
public function getFileName($file = null, $path = true)
{
$files = $this->getFiles($file, true, true);
$result = array();
$directory = "";
foreach ($files as $file) {
if (empty($this->files[$file]['name'])) {
continue;
}
if ($path === true) {
$directory = $this->getDestination($file) . DIRECTORY_SEPARATOR;
}
$result[$file] = $directory . $this->files[$file]['name'];
}
if (count($result) == 1) {
return current($result);
}
return $result;
}
/**
* Retrieve additional internal file informations for files
*
* @param string $file (Optional) File to get informations for
* @return array
*/
public function getFileInfo($file = null)
{
return $this->getFiles($file);
}
/**
* Sets a new destination for the given files
*
* @deprecated Will be changed to be a filter!!!
* @param string $destination New destination directory
* @param string|array $files Files to set the new destination for
* @return AbstractAdapter
* @throws Exception\InvalidArgumentException when the given destination is not a directory or does not exist
*/
public function setDestination($destination, $files = null)
{
$orig = $files;
$destination = rtrim($destination, "/\\");
if (!is_dir($destination)) {
throw new Exception\InvalidArgumentException('The given destination is not a directory or does not exist');
}
if (!is_writable($destination)) {
throw new Exception\InvalidArgumentException('The given destination is not writeable');
}
if ($files === null) {
foreach ($this->files as $file => $content) {
$this->files[$file]['destination'] = $destination;
}
} else {
$files = $this->getFiles($files, true, true);
if (empty($files) and is_string($orig)) {
$this->files[$orig]['destination'] = $destination;
}
foreach ($files as $file) {
$this->files[$file]['destination'] = $destination;
}
}
return $this;
}
/**
* Retrieve destination directory value
*
* @param null|string|array $files
* @throws Exception\InvalidArgumentException
* @return null|string|array
*/
public function getDestination($files = null)
{
$orig = $files;
$files = $this->getFiles($files, false, true);
$destinations = array();
if (empty($files) and is_string($orig)) {
if (isset($this->files[$orig]['destination'])) {
$destinations[$orig] = $this->files[$orig]['destination'];
} else {
throw new Exception\InvalidArgumentException(
sprintf('The file transfer adapter can not find "%s"', $orig)
);
}
}
foreach ($files as $key => $content) {
if (isset($this->files[$key]['destination'])) {
$destinations[$key] = $this->files[$key]['destination'];
} else {
$tmpdir = $this->getTmpDir();
$this->setDestination($tmpdir, $key);
$destinations[$key] = $tmpdir;
}
}
if (empty($destinations)) {
$destinations = $this->getTmpDir();
} elseif (count($destinations) == 1) {
$destinations = current($destinations);
}
return $destinations;
}
/**
* Sets translator to use in helper
*
* @param Translator $translator [optional] translator.
* Default is null, which sets no translator.
* @param string $textDomain [optional] text domain
* Default is null, which skips setTranslatorTextDomain
* @return AbstractAdapter
*/
public function setTranslator(Translator $translator = null, $textDomain = null)
{
$this->translator = $translator;
if (null !== $textDomain) {
$this->setTranslatorTextDomain($textDomain);
}
return $this;
}
/**
* Retrieve localization translator object
*
* @return Translator|null
*/
public function getTranslator()
{
if ($this->isTranslatorEnabled()) {
return null;
}
return $this->translator;
}
/**
* Checks if the helper has a translator
*
* @return bool
*/
public function hasTranslator()
{
return (bool) $this->getTranslator();
}
/**
* Indicate whether or not translation should be enabled
*
* @param bool $flag
* @return AbstractAdapter
*/
public function setTranslatorEnabled($flag = true)
{
$this->translatorEnabled = (bool) $flag;
return $this;
}
/**
* Is translation enabled?
*
* @return bool
*/
public function isTranslatorEnabled()
{
return $this->translatorEnabled;
}
/**
* Set translation text domain
*
* @param string $textDomain
* @return AbstractAdapter
*/
public function setTranslatorTextDomain($textDomain = 'default')
{
$this->translatorTextDomain = $textDomain;
return $this;
}
/**
* Return the translation text domain
*
* @return string
*/
public function getTranslatorTextDomain()
{
return $this->translatorTextDomain;
}
/**
* Returns the hash for a given file
*
* @param string $hash Hash algorithm to use
* @param string|array $files Files to return the hash for
* @return string|array Hashstring
* @throws Exception\InvalidArgumentException On unknown hash algorithm
*/
public function getHash($hash = 'crc32', $files = null)
{
if (!in_array($hash, hash_algos())) {
throw new Exception\InvalidArgumentException('Unknown hash algorithm');
}
$files = $this->getFiles($files);
$result = array();
foreach ($files as $key => $value) {
if (file_exists($value['name'])) {
$result[$key] = hash_file($hash, $value['name']);
} elseif (file_exists($value['tmp_name'])) {
$result[$key] = hash_file($hash, $value['tmp_name']);
} elseif (empty($value['options']['ignoreNoFile'])) {
throw new Exception\InvalidArgumentException("The file '{$value['name']}' does not exist");
}
}
if (count($result) == 1) {
return current($result);
}
return $result;
}
/**
* Returns the real filesize of the file
*
* @param string|array $files Files to get the filesize from
* @return string|array Filesize
* @throws Exception\InvalidArgumentException When the file does not exist
*/
public function getFileSize($files = null)
{
$files = $this->getFiles($files);
$result = array();
foreach ($files as $key => $value) {
if (file_exists($value['name']) || file_exists($value['tmp_name'])) {
if ($value['options']['useByteString']) {
$result[$key] = static::toByteString($value['size']);
} else {
$result[$key] = $value['size'];
}
} elseif (empty($value['options']['ignoreNoFile'])) {
throw new Exception\InvalidArgumentException("The file '{$value['name']}' does not exist");
} else {
continue;
}
}
if (count($result) == 1) {
return current($result);
}
return $result;
}
/**
* Internal method to detect the size of a file
*
* @param array $value File infos
* @return string Filesize of given file
*/
protected function detectFileSize($value)
{
if (file_exists($value['name'])) {
$filename = $value['name'];
} elseif (file_exists($value['tmp_name'])) {
$filename = $value['tmp_name'];
} else {
return null;
}
ErrorHandler::start();
$filesize = filesize($filename);
$return = ErrorHandler::stop();
if ($return instanceof ErrorException) {
$filesize = 0;
}
return sprintf("%u", $filesize);
}
/**
* Returns the real mimetype of the file
* Uses fileinfo, when not available mime_magic and as last fallback a manual given mimetype
*
* @param string|array $files Files to get the mimetype from
* @return string|array MimeType
* @throws Exception\InvalidArgumentException When the file does not exist
*/
public function getMimeType($files = null)
{
$files = $this->getFiles($files);
$result = array();
foreach ($files as $key => $value) {
if (file_exists($value['name']) || file_exists($value['tmp_name'])) {
$result[$key] = $value['type'];
} elseif (empty($value['options']['ignoreNoFile'])) {
throw new Exception\InvalidArgumentException("the file '{$value['name']}' does not exist");
} else {
continue;
}
}
if (count($result) == 1) {
return current($result);
}
return $result;
}
/**
* Internal method to detect the mime type of a file
*
* @param array $value File infos
* @return string Mimetype of given file
*/
protected function detectMimeType($value)
{
if (file_exists($value['name'])) {
$file = $value['name'];
} elseif (file_exists($value['tmp_name'])) {
$file = $value['tmp_name'];
} else {
return null;
}
if (class_exists('finfo', false)) {
if (!empty($value['options']['magicFile'])) {
ErrorHandler::start();
$mime = finfo_open(FILEINFO_MIME_TYPE, $value['options']['magicFile']);
ErrorHandler::stop();
}
if (empty($mime)) {
ErrorHandler::start();
$mime = finfo_open(FILEINFO_MIME_TYPE);
ErrorHandler::stop();
}
if (!empty($mime)) {
$result = finfo_file($mime, $file);
}
unset($mime);
}
if (empty($result) && (function_exists('mime_content_type')
&& ini_get('mime_magic.magicfile'))) {
$result = mime_content_type($file);
}
if (empty($result)) {
$result = 'application/octet-stream';
}
return $result;
}
/**
* Returns the formatted size
*
* @param integer $size
* @return string
*/
protected static function toByteString($size)
{
$sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
for ($i=0; $size >= 1024 && $i < 9; $i++) {
$size /= 1024;
}
return round($size, 2) . $sizes[$i];
}
/**
* Internal function to filter all given files
*
* @param string|array $files (Optional) Files to check
* @return bool False on error
*/
protected function filter($files = null)
{
$check = $this->getFiles($files);
foreach ($check as $name => $content) {
if (array_key_exists('filters', $content)) {
foreach ($content['filters'] as $class) {
$filter = $this->filters[$class];
try {
$result = $filter->filter($this->getFileName($name));
$this->files[$name]['destination'] = dirname($result);
$this->files[$name]['name'] = basename($result);
} catch (FilterException\ExceptionInterface $e) {
$this->messages += array($e->getMessage());
}
}
}
}
if (count($this->messages) > 0) {
return false;
}
return true;
}
/**
* Determine system TMP directory and detect if we have read access
*
* @return string
* @throws Exception\RuntimeException if unable to determine directory
*/
protected function getTmpDir()
{
if (null === $this->tmpDir) {
$tmpdir = array();
if (function_exists('sys_get_temp_dir')) {
$tmpdir[] = sys_get_temp_dir();
}
if (!empty($_ENV['TMP'])) {
$tmpdir[] = realpath($_ENV['TMP']);
}
if (!empty($_ENV['TMPDIR'])) {
$tmpdir[] = realpath($_ENV['TMPDIR']);
}
if (!empty($_ENV['TEMP'])) {
$tmpdir[] = realpath($_ENV['TEMP']);
}
$upload = ini_get('upload_tmp_dir');
if ($upload) {
$tmpdir[] = realpath($upload);
}
foreach ($tmpdir as $directory) {
if ($this->isPathWriteable($directory)) {
$this->tmpDir = $directory;
}
}
if (empty($this->tmpDir)) {
// Attemp to detect by creating a temporary file
$tempFile = tempnam(md5(uniqid(rand(), true)), '');
if ($tempFile) {
$this->tmpDir = realpath(dirname($tempFile));
unlink($tempFile);
} else {
throw new Exception\RuntimeException('Could not determine a temporary directory');
}
}
$this->tmpDir = rtrim($this->tmpDir, "/\\");
}
return $this->tmpDir;
}
/**
* Tries to detect if we can read and write to the given path
*
* @param string $path
* @return bool
*/
protected function isPathWriteable($path)
{
$tempFile = rtrim($path, "/\\");
$tempFile .= '/' . 'test.1';
ErrorHandler::start();
$result = file_put_contents($tempFile, 'TEST');
ErrorHandler::stop();
if ($result == false) {
return false;
}
ErrorHandler::start();
$result = unlink($tempFile);
ErrorHandler::stop();
if ($result == false) {
return false;
}
return true;
}
/**
* Returns found files based on internal file array and given files
*
* @param string|array $files (Optional) Files to return
* @param bool $names (Optional) Returns only names on true, else complete info
* @param bool $noexception (Optional) Allows throwing an exception, otherwise returns an empty array
* @return array Found files
* @throws Exception\RuntimeException On false filename
*/
protected function getFiles($files, $names = false, $noexception = false)
{
$check = array();
if (is_string($files)) {
$files = array($files);
}
if (is_array($files)) {
foreach ($files as $find) {
$found = array();
foreach ($this->files as $file => $content) {
if (!isset($content['name'])) {
continue;
}
if (($content['name'] === $find) && isset($content['multifiles'])) {
foreach ($content['multifiles'] as $multifile) {
$found[] = $multifile;
}
break;
}
if ($file === $find) {
$found[] = $file;
break;
}
if ($content['name'] === $find) {
$found[] = $file;
break;
}
}
if (empty($found)) {
if ($noexception !== false) {
return array();
}
throw new Exception\RuntimeException(sprintf('The file transfer adapter can not find "%s"', $find));
}
foreach ($found as $checked) {
$check[$checked] = $this->files[$checked];
}
}
}
if ($files === null) {
$check = $this->files;
$keys = array_keys($check);
foreach ($keys as $key) {
if (isset($check[$key]['multifiles'])) {
unset($check[$key]);
}
}
}
if ($names) {
$check = array_keys($check);
}
return $check;
}
/**
* Retrieve internal identifier for a named validator
*
* @param string $name
* @return string
*/
protected function getValidatorIdentifier($name)
{
if (array_key_exists($name, $this->validators)) {
return $name;
}
foreach (array_keys($this->validators) as $test) {
if (preg_match('/' . preg_quote($name) . '$/i', $test)) {
return $test;
}
}
return false;
}
/**
* Retrieve internal identifier for a named filter
*
* @param string $name
* @return string
*/
protected function getFilterIdentifier($name)
{
if (array_key_exists($name, $this->filters)) {
return $name;
}
foreach (array_keys($this->filters) as $test) {
if (preg_match('/' . preg_quote($name) . '$/i', $test)) {
return $test;
}
}
return false;
}
}
Jump to Line
Something went wrong with that request. Please try again.