diff --git a/.travis.yml b/.travis.yml index ee3a30bec..429f28631 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,3 @@ -sudo: false - language: php branches: @@ -59,6 +57,15 @@ matrix: - php: 7.2 env: - DEPS=latest + - php: 7.3 + env: + - DEPS=lowest + - php: 7.3 + env: + - DEPS=locked + - php: 7.3 + env: + - DEPS=latest before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f74a0494..7b3e99ea9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,30 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. +## 2.12.0 - 2019-01-30 + +### Added + +- [#250](https://github.com/zendframework/zend-validator/pull/250) adds support for PHP 7.3. + +### Changed + +- [#251](https://github.com/zendframework/zend-validator/pull/251) updates the logic of each of the various `Zend\Validator\File` validators + to allow validating against PSR-7 `UploadedFileInterface` instances, expanding + the support originally provided in version 2.11.0. + +### Deprecated + +- Nothing. + +### Removed + +- [#250](https://github.com/zendframework/zend-validator/pull/250) removes support for zend-stdlib v2 releases. + +### Fixed + +- Nothing. + ## 2.11.1 - 2019-01-29 ### Added diff --git a/composer.json b/composer.json index fc087554c..ded80c0dd 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ }, "require": { "php": "^5.6 || ^7.0", - "zendframework/zend-stdlib": "^2.7.6 || ^3.1", + "zendframework/zend-stdlib": "^3.2.1", "container-interop/container-interop": "^1.1" }, "require-dev": { @@ -47,8 +47,8 @@ "prefer-stable": true, "extra": { "branch-alias": { - "dev-master": "2.11.x-dev", - "dev-develop": "2.12.x-dev" + "dev-master": "2.12.x-dev", + "dev-develop": "2.13.x-dev" }, "zf": { "component": "Zend\\Validator", diff --git a/composer.lock b/composer.lock index fd89f9643..c95242d4f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6d7da53324a7d53b31d05453a72e1136", + "content-hash": "d63c66fe8848c902d47f6175d0d73710", "packages": [ { "name": "container-interop/container-interop", diff --git a/src/DateStep.php b/src/DateStep.php index 8696cd562..bbb8b9e81 100644 --- a/src/DateStep.php +++ b/src/DateStep.php @@ -166,10 +166,10 @@ protected function convertString($value, $addErrors = true) if (strpos($this->format, 'Y-\WW') === 0 && preg_match('/^([0-9]{4})\-W([0-9]{2})/', $value, $matches) ) { - $date = new DateTime; + $date = new DateTime(); $date->setISODate($matches[1], $matches[2]); } else { - $date = DateTime::createFromFormat($this->format, $value, $this->timezone); + $date = DateTime::createFromFormat($this->format, $value, new DateTimeZone('UTC')); } // Invalid dates can show up as warnings (ie. "2007-02-99") diff --git a/src/File/Crc32.php b/src/File/Crc32.php index 126d63d56..9c225a1f4 100644 --- a/src/File/Crc32.php +++ b/src/File/Crc32.php @@ -9,13 +9,15 @@ namespace Zend\Validator\File; -use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the crc32 hash of given files */ class Crc32 extends Hash { + use FileInformationTrait; + /** * @const string Error constants */ @@ -85,32 +87,18 @@ public function addCrc32($options) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } $hashes = array_unique(array_keys($this->getHash())); - $filehash = hash_file('crc32', $file); + $filehash = hash_file('crc32', $fileInfo['file']); if ($filehash === false) { $this->error(self::NOT_DETECTED); return false; diff --git a/src/File/ExcludeExtension.php b/src/File/ExcludeExtension.php index 1d1cb4218..9f8d3e034 100644 --- a/src/File/ExcludeExtension.php +++ b/src/File/ExcludeExtension.php @@ -9,6 +9,7 @@ namespace Zend\Validator\File; +use Zend\Validator\File\FileInformationTrait; use Zend\Validator\Exception; /** @@ -16,6 +17,8 @@ */ class ExcludeExtension extends Extension { + use FileInformationTrait; + /** * @const string Error constants */ @@ -40,31 +43,17 @@ class ExcludeExtension extends Extension */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } - $extension = substr($filename, strrpos($filename, '.') + 1); + $extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1); $extensions = $this->getExtension(); if ($this->getCase() && (! in_array($extension, $extensions))) { diff --git a/src/File/ExcludeMimeType.php b/src/File/ExcludeMimeType.php index 66c8eadb6..b217c9219 100644 --- a/src/File/ExcludeMimeType.php +++ b/src/File/ExcludeMimeType.php @@ -10,13 +10,15 @@ namespace Zend\Validator\File; use finfo; -use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the mime type of a file */ class ExcludeMimeType extends MimeType { + use FileInformationTrait; + const FALSE_TYPE = 'fileExcludeMimeTypeFalse'; const NOT_DETECTED = 'fileExcludeMimeTypeNotDetected'; const NOT_READABLE = 'fileExcludeMimeTypeNotReadable'; @@ -41,29 +43,12 @@ class ExcludeMimeType extends MimeType */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $filetype = $file['type']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name']) || ! isset($value['type'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - $filetype = $value['type']; - } else { - $file = $value; - $filename = basename($file); - $filetype = null; - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file, true); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_READABLE); return false; } @@ -80,12 +65,12 @@ public function isValid($value, $file = null) $this->type = null; if (! empty($this->finfo)) { - $this->type = finfo_file($this->finfo, $file); + $this->type = finfo_file($this->finfo, $fileInfo['file']); } } if (empty($this->type) && $this->getHeaderCheck()) { - $this->type = $filetype; + $this->type = $fileInfo['filetype']; } if (empty($this->type)) { diff --git a/src/File/Exists.php b/src/File/Exists.php index 817be1658..9968cc6cb 100644 --- a/src/File/Exists.php +++ b/src/File/Exists.php @@ -11,12 +11,15 @@ use Zend\Validator\AbstractValidator; use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator which checks if the file already exists in the directory */ class Exists extends AbstractValidator { + use FileInformationTrait; + /** * @const string Error constants */ @@ -144,31 +147,15 @@ public function addDirectory($directory) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - $this->setValue($filename); - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = basename($file); - $this->setValue($value['name']); - } else { - $file = $value; - $filename = basename($file); - $this->setValue($filename); - } + $fileInfo = $this->getFileInfo($value, $file, false, true); + + $this->setValue($fileInfo['filename']); $check = false; $directories = $this->getDirectory(true); if (! isset($directories)) { $check = true; - if (! file_exists($file)) { + if (! file_exists($fileInfo['file'])) { $this->error(self::DOES_NOT_EXIST); return false; } @@ -179,7 +166,7 @@ public function isValid($value, $file = null) } $check = true; - if (! file_exists($directory . DIRECTORY_SEPARATOR . $filename)) { + if (! file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) { $this->error(self::DOES_NOT_EXIST); return false; } diff --git a/src/File/Extension.php b/src/File/Extension.php index e502dc993..0e1cd9ed0 100644 --- a/src/File/Extension.php +++ b/src/File/Extension.php @@ -12,6 +12,7 @@ use Traversable; use Zend\Stdlib\ArrayUtils; use Zend\Validator\AbstractValidator; +use Zend\Validator\File\FileInformationTrait; use Zend\Validator\Exception; /** @@ -19,6 +20,8 @@ */ class Extension extends AbstractValidator { + use FileInformationTrait; + /** * @const string Error constants */ @@ -177,31 +180,17 @@ public function addExtension($extension) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } - $extension = substr($filename, strrpos($filename, '.') + 1); + $extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1); $extensions = $this->getExtension(); if ($this->getCase() && (in_array($extension, $extensions))) { diff --git a/src/File/FileInformationTrait.php b/src/File/FileInformationTrait.php new file mode 100644 index 000000000..7985f0eab --- /dev/null +++ b/src/File/FileInformationTrait.php @@ -0,0 +1,166 @@ +getLegacyFileInfo($file, $hasType, $hasBasename); + } + + if (is_array($value)) { + return $this->getSapiFileInfo($value, $hasType, $hasBasename); + } + + if ($value instanceof UploadedFileInterface) { + return $this->getPsr7FileInfo($value, $hasType, $hasBasename); + } + + return $this->getFileBasedFileInfo($value, $hasType, $hasBasename); + } + + /** + * Generate file information array with legacy Zend_File_Transfer API + * + * @param array $file File data + * @param bool $hasType Return with filetype + * @param bool $hasBasename Basename is calculated from location path + * @return array + */ + private function getLegacyFileInfo( + array $file, + $hasType = false, + $hasBasename = false + ) { + $fileInfo = []; + + $fileInfo['filename'] = $file['name']; + $fileInfo['file'] = $file['tmp_name']; + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = $file['type']; + } + + return $fileInfo; + } + + /** + * Generate file information array with SAPI + * + * @param array $file File data from SAPI + * @param bool $hasType Return with filetype + * @param bool $hasBasename Filename is calculated from location path + * @return array + */ + private function getSapiFileInfo( + array $file, + $hasType = false, + $hasBasename = false + ) { + if (! isset($file['tmp_name']) || ! isset($file['name'])) { + throw new Exception\InvalidArgumentException( + 'Value array must be in $_FILES format' + ); + } + + $fileInfo = []; + + $fileInfo['file'] = $file['tmp_name']; + $fileInfo['filename'] = $file['name']; + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = $file['type']; + } + + return $fileInfo; + } + + /** + * Generate file information array with PSR-7 UploadedFileInterface + * + * @param UploadedFileInterface $file + * @param bool $hasType Return with filetype + * @param bool $hasBasename Filename is calculated from location path + * @return array + */ + private function getPsr7FileInfo( + UploadedFileInterface $file, + $hasType = false, + $hasBasename = false + ) { + $fileInfo = []; + + $fileInfo['file'] = $file->getStream()->getMetadata('uri'); + $fileInfo['filename'] = $file->getClientFilename(); + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = $file->getClientMediaType(); + } + + return $fileInfo; + } + + /** + * Generate file information array with base method + * + * @param string $file File path + * @param bool $hasType Return with filetype + * @param bool $hasBasename Filename is calculated from location path + * @return array + */ + private function getFileBasedFileInfo( + $file, + $hasType = false, + $hasBasename = false + ) { + $fileInfo = []; + + $fileInfo['file'] = $file; + $fileInfo['filename'] = basename($fileInfo['file']); + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = null; + } + + return $fileInfo; + } +} diff --git a/src/File/Hash.php b/src/File/Hash.php index f48c2c921..54a47c284 100644 --- a/src/File/Hash.php +++ b/src/File/Hash.php @@ -11,12 +11,15 @@ use Zend\Validator\AbstractValidator; use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the hash of given files */ class Hash extends AbstractValidator { + use FileInformationTrait; + /** * @const string Error constants */ @@ -129,34 +132,22 @@ public function addHash($options) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } $algos = array_unique(array_values($this->getHash())); $hashes = array_unique(array_keys($this->getHash())); + foreach ($algos as $algorithm) { - $filehash = hash_file($algorithm, $file); + $filehash = hash_file($algorithm, $fileInfo['file']); + if ($filehash === false) { $this->error(self::NOT_DETECTED); return false; diff --git a/src/File/ImageSize.php b/src/File/ImageSize.php index 47fe12914..8ea1dad3e 100644 --- a/src/File/ImageSize.php +++ b/src/File/ImageSize.php @@ -12,12 +12,15 @@ use Zend\Stdlib\ErrorHandler; use Zend\Validator\AbstractValidator; use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the image size of an image file */ class ImageSize extends AbstractValidator { + use FileInformationTrait; + /** * @const string Error constants */ @@ -332,32 +335,18 @@ public function setImageHeight($options) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_READABLE); return false; } ErrorHandler::start(); - $size = getimagesize($file); + $size = getimagesize($fileInfo['file']); ErrorHandler::stop(); if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) { diff --git a/src/File/Md5.php b/src/File/Md5.php index c36b8a457..aa60ff3cd 100644 --- a/src/File/Md5.php +++ b/src/File/Md5.php @@ -9,13 +9,15 @@ namespace Zend\Validator\File; -use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the md5 hash of given files */ class Md5 extends Hash { + use FileInformationTrait; + /** * @const string Error constants */ @@ -85,32 +87,18 @@ public function addMd5($options) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } $hashes = array_unique(array_keys($this->getHash())); - $filehash = hash_file('md5', $file); + $filehash = hash_file('md5', $fileInfo['file']); if ($filehash === false) { $this->error(self::NOT_DETECTED); return false; diff --git a/src/File/MimeType.php b/src/File/MimeType.php index 3a9d42e6f..7ef3d6ede 100644 --- a/src/File/MimeType.php +++ b/src/File/MimeType.php @@ -14,12 +14,15 @@ use Zend\Stdlib\ErrorHandler; use Zend\Validator\AbstractValidator; use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the mime type of a file */ class MimeType extends AbstractValidator { + use FileInformationTrait; + /**#@+ * @const Error type constants */ @@ -341,29 +344,12 @@ public function addMimeType($mimetype) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $filetype = $file['type']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name']) || ! isset($value['type'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - $filetype = $value['type']; - } else { - $file = $value; - $filename = basename($file); - $filetype = null; - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file, true); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(static::NOT_READABLE); return false; } @@ -384,13 +370,13 @@ public function isValid($value, $file = null) $this->type = null; if (! empty($this->finfo)) { - $this->type = finfo_file($this->finfo, $file); + $this->type = finfo_file($this->finfo, $fileInfo['file']); unset($this->finfo); } } if (empty($this->type) && $this->getHeaderCheck()) { - $this->type = $filetype; + $this->type = $fileInfo['filetype']; } if (empty($this->type)) { diff --git a/src/File/NotExists.php b/src/File/NotExists.php index 1128e6c6f..324400fb6 100644 --- a/src/File/NotExists.php +++ b/src/File/NotExists.php @@ -10,12 +10,15 @@ namespace Zend\Validator\File; use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator which checks if the destination file does not exist */ class NotExists extends Exists { + use FileInformationTrait; + /** * @const string Error constants */ @@ -37,31 +40,15 @@ class NotExists extends Exists */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - $this->setValue($filename); - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = basename($file); - $this->setValue($value['name']); - } else { - $file = $value; - $filename = basename($file); - $this->setValue($filename); - } + $fileInfo = $this->getFileInfo($value, $file, false, true); + + $this->setValue($fileInfo['filename']); $check = false; $directories = $this->getDirectory(true); if (! isset($directories)) { $check = true; - if (file_exists($file)) { + if (file_exists($fileInfo['file'])) { $this->error(self::DOES_EXIST); return false; } @@ -72,7 +59,7 @@ public function isValid($value, $file = null) } $check = true; - if (file_exists($directory . DIRECTORY_SEPARATOR . $filename)) { + if (file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) { $this->error(self::DOES_EXIST); return false; } diff --git a/src/File/Sha1.php b/src/File/Sha1.php index bc3929d1f..03eebc74f 100644 --- a/src/File/Sha1.php +++ b/src/File/Sha1.php @@ -9,13 +9,15 @@ namespace Zend\Validator\File; -use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the sha1 hash of given files */ class Sha1 extends Hash { + use FileInformationTrait; + /** * @const string Error constants */ @@ -85,32 +87,18 @@ public function addSha1($options) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } $hashes = array_unique(array_keys($this->getHash())); - $filehash = hash_file('sha1', $file); + $filehash = hash_file('sha1', $fileInfo['file']); if ($filehash === false) { $this->error(self::NOT_DETECTED); return false; diff --git a/src/File/Size.php b/src/File/Size.php index 45b90c01e..b45b13255 100644 --- a/src/File/Size.php +++ b/src/File/Size.php @@ -12,12 +12,15 @@ use Zend\Stdlib\ErrorHandler; use Zend\Validator\AbstractValidator; use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for the maximum size of a file up to a max of 2GB */ class Size extends AbstractValidator { + use FileInformationTrait; + /** * @const string Error constants */ @@ -234,33 +237,19 @@ protected function setSize($size) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } // limited to 4GB files ErrorHandler::start(); - $size = sprintf("%u", filesize($file)); + $size = sprintf("%u", filesize($fileInfo['file'])); ErrorHandler::stop(); $this->size = $size; diff --git a/src/File/WordCount.php b/src/File/WordCount.php index cbe9ce451..049e331a5 100644 --- a/src/File/WordCount.php +++ b/src/File/WordCount.php @@ -11,12 +11,15 @@ use Zend\Validator\AbstractValidator; use Zend\Validator\Exception; +use Zend\Validator\File\FileInformationTrait; /** * Validator for counting all words in a file */ class WordCount extends AbstractValidator { + use FileInformationTrait; + /** * @const string Error constants */ @@ -175,31 +178,17 @@ public function setMax($max) */ public function isValid($value, $file = null) { - if (is_string($value) && is_array($file)) { - // Legacy Zend\Transfer API support - $filename = $file['name']; - $file = $file['tmp_name']; - } elseif (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $value['tmp_name']; - $filename = $value['name']; - } else { - $file = $value; - $filename = basename($file); - } - $this->setValue($filename); + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); // Is file readable ? - if (empty($file) || false === is_readable($file)) { + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { $this->error(self::NOT_FOUND); return false; } - $content = file_get_contents($file); + $content = file_get_contents($fileInfo['file']); $this->count = str_word_count($content); if (($this->getMax() !== null) && ($this->count > $this->getMax())) { $this->error(self::TOO_MUCH); diff --git a/src/Hostname.php b/src/Hostname.php index 02ddd1ab9..5a85ffb88 100644 --- a/src/Hostname.php +++ b/src/Hostname.php @@ -69,7 +69,7 @@ class Hostname extends AbstractValidator /** * Array of valid top-level-domains - * IanaVersion 2018121300 + * IanaVersion 2019012900 * * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain * @see http://www.iana.org/domains/root/db/ Official list of supported TLDs @@ -1228,7 +1228,6 @@ class Hostname extends AbstractValidator 'sony', 'soy', 'space', - 'spiegel', 'sport', 'spot', 'spreadbetting', diff --git a/test/File/FileInformationTraitTest.php b/test/File/FileInformationTraitTest.php new file mode 100644 index 000000000..9c63dd5bd --- /dev/null +++ b/test/File/FileInformationTraitTest.php @@ -0,0 +1,283 @@ +stream = $this->prophesize(StreamInterface::class); + $this->upload = $this->prophesize(UploadedFileInterface::class); + } + + public function testLegacyFileInfoBasic() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + $basename = basename($testFile); + $file = [ + 'name' => $basename, + 'tmp_name' => $testFile + ]; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $basename, + $file + ); + + $this->assertEquals($fileInfo, [ + 'filename' => $file['name'], + 'file' => $file['tmp_name'], + ]); + } + + public function testLegacyFileInfoWithFiletype() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + $basename = basename($testFile); + $file = [ + 'name' => $basename, + 'tmp_name' => $testFile, + 'type' => 'mo', + ]; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $basename, + $file, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => $file['name'], + 'file' => $file['tmp_name'], + 'filetype' => $file['type'], + ]); + } + + public function testLegacyFileInfoWithBasename() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + $basename = basename($testFile); + $file = [ + 'name' => $basename, + 'tmp_name' => $testFile, + ]; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $basename, + $file, + false, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => $file['name'], + 'file' => $file['tmp_name'], + 'basename' => basename($file['tmp_name']), + ]); + } + + public function testSapiFileInfoBasic() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + $file = [ + 'name' => basename($testFile), + 'tmp_name' => $testFile + ]; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $file + ); + + $this->assertEquals($fileInfo, [ + 'filename' => $file['name'], + 'file' => $file['tmp_name'], + ]); + } + + public function testSapiFileInfoWithFiletype() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + $file = [ + 'name' => basename($testFile), + 'tmp_name' => $testFile, + 'type' => 'mo', + ]; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $file, + null, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => $file['name'], + 'file' => $file['tmp_name'], + 'filetype' => $file['type'], + ]); + } + + public function testSapiFileInfoWithBasename() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + $file = [ + 'name' => basename($testFile), + 'tmp_name' => $testFile, + ]; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $file, + null, + false, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => $file['name'], + 'file' => $file['tmp_name'], + 'basename' => basename($file['tmp_name']), + ]); + } + + public function testPsr7FileInfoBasic() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + + $this->stream->getMetadata('uri')->willReturn($testFile); + $this->upload->getClientFilename()->willReturn(basename($testFile)); + $this->upload->getClientMediaType()->willReturn(mime_content_type($testFile)); + $this->upload->getStream()->willReturn($this->stream->reveal()); + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $this->upload->reveal() + ); + + $this->assertEquals($fileInfo, [ + 'filename' => basename($testFile), + 'file' => $testFile, + ]); + } + + public function testPsr7FileInfoBasicWithFiletype() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + + $this->stream->getMetadata('uri')->willReturn($testFile); + $this->upload->getClientFilename()->willReturn(basename($testFile)); + $this->upload->getClientMediaType()->willReturn(mime_content_type($testFile)); + $this->upload->getStream()->willReturn($this->stream->reveal()); + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $this->upload->reveal(), + null, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => basename($testFile), + 'file' => $testFile, + 'filetype' => mime_content_type($testFile), + ]); + } + + public function testPsr7FileInfoBasicWithBasename() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + + $this->stream->getMetadata('uri')->willReturn($testFile); + $this->upload->getClientFilename()->willReturn(basename($testFile)); + $this->upload->getClientMediaType()->willReturn(mime_content_type($testFile)); + $this->upload->getStream()->willReturn($this->stream->reveal()); + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $this->upload->reveal(), + null, + false, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => basename($testFile), + 'file' => $testFile, + 'basename' => basename($testFile), + ]); + } + + public function testFileBasedFileInfoBasic() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $testFile + ); + + $this->assertEquals($fileInfo, [ + 'filename' => basename($testFile), + 'file' => $testFile, + ]); + } + + public function testFileBasedFileInfoBasicWithFiletype() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $testFile, + null, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => basename($testFile), + 'file' => $testFile, + 'filetype' => null + ]); + } + + public function testFileBasedFileInfoBasicWithBasename() + { + $testFile = __DIR__ . '/_files/testsize.mo'; + + $fileInformation = new FileInformation(); + $fileInfo = $fileInformation->checkFileInformation( + $testFile, + null, + false, + true + ); + + $this->assertEquals($fileInfo, [ + 'filename' => basename($testFile), + 'file' => $testFile, + 'basename' => basename($testFile) + ]); + } +} diff --git a/test/File/TestAsset/FileInformation.php b/test/File/TestAsset/FileInformation.php new file mode 100644 index 000000000..0a3e6fdb2 --- /dev/null +++ b/test/File/TestAsset/FileInformation.php @@ -0,0 +1,36 @@ +getFileInfo($value, $file, $hasType, $hasBasename); + } +}