diff --git a/.travis.yml b/.travis.yml index 3c5f852b..a999c83e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,13 +16,16 @@ matrix: - php: 5.6 env: - DEPS=lowest + - REMOVE_DEV_DEPS="psr/http-factory" - php: 5.6 env: - DEPS=locked - - LEGACY_DEPS="phpunit/phpunit" + - REMOVE_DEV_DEPS="psr/http-factory" + - LEGACY_DEPS="phpunit/phpunit zendframework/zend-crypt psr/http-factory" - php: 5.6 env: - DEPS=latest + - REMOVE_DEV_DEPS="psr/http-factory" - php: 7 env: - DEPS=lowest @@ -56,6 +59,7 @@ matrix: before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi + - if [[ $REMOVE_DEV_DEPS != '' ]]; then travis_retry composer remove $COMPOSER_ARGS --dev --no-update $REMOVE_DEV_DEPS ; fi install: - travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a80b218..daf01e13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ All notable changes to this project will be documented in this file, in reverse ### Added +- [#70](https://github.com/zendframework/zend-inputfilter/pull/70) Adds compatibility with the PSR-7 `UploadedFileInterface` to the + `RenameUpload` filter. + - [#71](https://github.com/zendframework/zend-filter/pull/71) adds the `ToFloat` filter, to complement the `ToInt` filter. - [#69](https://github.com/zendframework/zend-filter/pull/69) adds `Zend\Filter\StringSufix`; when provided with a string `suffix` diff --git a/composer.json b/composer.json index 7c5e6f78..bf193dce 100644 --- a/composer.json +++ b/composer.json @@ -22,12 +22,14 @@ "require-dev": { "pear/archive_tar": "^1.4.3", "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "psr/http-factory": "^1.0", "zendframework/zend-coding-standard": "~1.0.0", "zendframework/zend-crypt": "^3.2.1", "zendframework/zend-servicemanager": "^2.7.8 || ^3.3", "zendframework/zend-uri": "^2.6" }, "suggest": { + "psr/http-factory-implementation": "psr/http-factory-implementation, for creating file upload instances when consuming PSR-7 in file upload filters", "zendframework/zend-crypt": "Zend\\Crypt component, for encryption filters", "zendframework/zend-i18n": "Zend\\I18n component for filters depending on i18n functionality", "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for using the filter chain functionality", diff --git a/composer.lock b/composer.lock index abe5baa1..55ea65ca 100644 --- a/composer.lock +++ b/composer.lock @@ -4,35 +4,35 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d22cfff49849018c6c33519d66c17694", + "content-hash": "8f485a1e7bde7af92b19d3c29fc203fc", "packages": [ { "name": "zendframework/zend-stdlib", - "version": "3.1.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78" + "reference": "66536006722aff9e62d1b331025089b7ec71c065" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/debedcfc373a293f9250cc9aa03cf121428c8e78", - "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/66536006722aff9e62d1b331025089b7ec71c065", + "reference": "66536006722aff9e62d1b331025089b7ec71c065", "shasum": "" }, "require": { "php": "^5.6 || ^7.0" }, "require-dev": { - "athletic/athletic": "~0.1", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "^2.6.2" + "phpbench/phpbench": "^0.13", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev", - "dev-develop": "3.2-dev" + "dev-master": "3.2.x-dev", + "dev-develop": "3.3.x-dev" } }, "autoload": { @@ -44,12 +44,13 @@ "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-stdlib", + "description": "SPL extensions, array utilities, error handlers, and more", "keywords": [ + "ZendFramework", "stdlib", - "zf2" + "zf" ], - "time": "2016-09-13T14:38:50+00:00" + "time": "2018-08-28T21:34:05+00:00" } ], "packages-dev": [ @@ -140,25 +141,28 @@ }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { @@ -181,37 +185,33 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" + "time": "2018-06-11T23:09:50+00:00" }, { "name": "paragonie/random_compat", - "version": "v2.0.12", + "version": "v9.99.99", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", "shasum": "" }, "require": { - "php": ">=5.2.0" + "php": "^7" }, "require-dev": { - "phpunit/phpunit": "4.*|5.*" + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" }, "suggest": { "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." }, "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -226,10 +226,11 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", + "polyfill", "pseudorandom", "random" ], - "time": "2018-04-04T21:24:14+00:00" + "time": "2018-07-02T15:55:56+00:00" }, { "name": "pear/archive_tar", @@ -346,16 +347,16 @@ }, { "name": "pear/pear-core-minimal", - "version": "v1.10.3", + "version": "v1.10.7", "source": { "type": "git", "url": "https://github.com/pear/pear-core-minimal.git", - "reference": "070f0b600b2caca2501e2c9b7e553016e4b0d115" + "reference": "19a3e0fcd50492c4357372f623f55f1b144346da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/070f0b600b2caca2501e2c9b7e553016e4b0d115", - "reference": "070f0b600b2caca2501e2c9b7e553016e4b0d115", + "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/19a3e0fcd50492c4357372f623f55f1b144346da", + "reference": "19a3e0fcd50492c4357372f623f55f1b144346da", "shasum": "" }, "require": { @@ -386,7 +387,7 @@ } ], "description": "Minimal set of PEAR core files to be used as composer dependency", - "time": "2017-02-28T16:46:11+00:00" + "time": "2018-12-05T20:03:52+00:00" }, { "name": "pear/pear_exception", @@ -699,33 +700,33 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.5", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.8.x-dev" } }, "autoload": { @@ -758,7 +759,7 @@ "spy", "stub" ], - "time": "2018-02-19T10:16:54+00:00" + "time": "2018-08-05T17:53:17+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1011,16 +1012,16 @@ }, { "name": "phpunit/phpunit", - "version": "6.5.8", + "version": "6.5.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b" + "reference": "0973426fb012359b2f18d3bd1e90ef1172839693" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4f21a3c6b97c42952fd5c2837bb354ec0199b97b", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0973426fb012359b2f18d3bd1e90ef1172839693", + "reference": "0973426fb012359b2f18d3bd1e90ef1172839693", "shasum": "" }, "require": { @@ -1038,7 +1039,7 @@ "phpunit/php-file-iterator": "^1.4.3", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^5.0.5", + "phpunit/phpunit-mock-objects": "^5.0.9", "sebastian/comparator": "^2.1", "sebastian/diff": "^2.0", "sebastian/environment": "^3.1", @@ -1091,20 +1092,20 @@ "testing", "xunit" ], - "time": "2018-04-10T11:38:34+00:00" + "time": "2018-09-08T15:10:43+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "5.0.6", + "version": "5.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/cd1cf05c553ecfec36b170070573e540b67d3f1f", + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f", "shasum": "" }, "require": { @@ -1117,7 +1118,7 @@ "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "^6.5" + "phpunit/phpunit": "^6.5.11" }, "suggest": { "ext-soap": "*" @@ -1150,7 +1151,7 @@ "mock", "xunit" ], - "time": "2018-01-06T05:45:45+00:00" + "time": "2018-08-09T05:50:03+00:00" }, { "name": "psr/container", @@ -1201,6 +1202,108 @@ ], "time": "2017-02-14T16:28:37+00:00" }, + { + "name": "psr/http-factory", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "378bfe27931ecc54ff824a20d6f6bfc303bbd04c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/378bfe27931ecc54ff824a20d6f6bfc303bbd04c", + "reference": "378bfe27931ecc54ff824a20d6f6bfc303bbd04c", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2018-07-30T21:54:04+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", @@ -1762,16 +1865,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "2.9.1", + "version": "2.9.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" + "reference": "2acf168de78487db620ab4bc524135a13cfe6745" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", + "reference": "2acf168de78487db620ab4bc524135a13cfe6745", "shasum": "" }, "require": { @@ -1836,7 +1939,7 @@ "phpcs", "standards" ], - "time": "2017-05-22T02:43:20+00:00" + "time": "2018-11-07T22:31:41+00:00" }, { "name": "theseer/tokenizer", @@ -1959,28 +2062,28 @@ }, { "name": "zendframework/zend-crypt", - "version": "3.2.1", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-crypt.git", - "reference": "514cef5556bac069e36c2cbded40e529b86bb3f2" + "reference": "9c2916faa9b2132a0f91cdca8e95b025c352f065" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-crypt/zipball/514cef5556bac069e36c2cbded40e529b86bb3f2", - "reference": "514cef5556bac069e36c2cbded40e529b86bb3f2", + "url": "https://api.github.com/repos/zendframework/zend-crypt/zipball/9c2916faa9b2132a0f91cdca8e95b025c352f065", + "reference": "9c2916faa9b2132a0f91cdca8e95b025c352f065", "shasum": "" }, "require": { - "container-interop/container-interop": "~1.0", + "container-interop/container-interop": "^1.2", "ext-mbstring": "*", "php": "^5.6 || ^7.0", "zendframework/zend-math": "^3.0", - "zendframework/zend-stdlib": "^2.7 || ^3.0" + "zendframework/zend-stdlib": "^2.7.7 || ^3.1" }, "require-dev": { - "phpunit/phpunit": "^5.6.7", - "squizlabs/php_codesniffer": "^2.3.1" + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0" }, "suggest": { "ext-openssl": "Required for most features of Zend\\Crypt" @@ -1988,8 +2091,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev", - "dev-develop": "3.2-dev" + "dev-master": "3.3.x-dev", + "dev-develop": "3.4.x-dev" } }, "autoload": { @@ -2001,39 +2104,40 @@ "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-crypt", + "description": "Strong cryptography tools and password hashing", "keywords": [ + "ZendFramework", "crypt", - "zf2" + "zf" ], - "time": "2017-07-17T15:46:00+00:00" + "time": "2018-04-24T22:01:58+00:00" }, { "name": "zendframework/zend-escaper", - "version": "2.5.2", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-escaper.git", - "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e" + "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/2dcd14b61a72d8b8e27d579c6344e12c26141d4e", - "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e", + "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/31d8aafae982f9568287cb4dce987e6aff8fd074", + "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^5.6 || ^7.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.6.x-dev", + "dev-develop": "2.7.x-dev" } }, "autoload": { @@ -2045,35 +2149,36 @@ "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-escaper", + "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", "keywords": [ + "ZendFramework", "escaper", - "zf2" + "zf" ], - "time": "2016-06-30T19:48:38+00:00" + "time": "2018-04-25T15:48:53+00:00" }, { "name": "zendframework/zend-math", - "version": "3.0.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-math.git", - "reference": "fda3b4e6c3bb15c35adc6db38b2eacabaa243e65" + "reference": "07e43d87fd5c7edc4f54121b9a4625eb10e4b726" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-math/zipball/fda3b4e6c3bb15c35adc6db38b2eacabaa243e65", - "reference": "fda3b4e6c3bb15c35adc6db38b2eacabaa243e65", + "url": "https://api.github.com/repos/zendframework/zend-math/zipball/07e43d87fd5c7edc4f54121b9a4625eb10e4b726", + "reference": "07e43d87fd5c7edc4f54121b9a4625eb10e4b726", "shasum": "" }, "require": { "ext-mbstring": "*", - "paragonie/random_compat": "^2.0.2", - "php": "^5.5 || ^7.0" + "paragonie/random_compat": "^2.0.11 || 9.99.99", + "php": "^5.6 || ^7.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0" }, "suggest": { "ext-bcmath": "If using the bcmath functionality", @@ -2082,8 +2187,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev", - "dev-develop": "3.1-dev" + "dev-master": "3.2.x-dev", + "dev-develop": "3.3.x-dev" } }, "autoload": { @@ -2095,12 +2200,13 @@ "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-math", + "description": "Create cryptographically secure pseudo-random numbers, and manage big integers", "keywords": [ + "ZendFramework", "math", - "zf2" + "zf" ], - "time": "2016-04-28T17:37:42+00:00" + "time": "2018-12-04T15:45:09+00:00" }, { "name": "zendframework/zend-servicemanager", @@ -2172,25 +2278,25 @@ }, { "name": "zendframework/zend-uri", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-uri.git", - "reference": "fb998b9487ea8c5f4aaac0e536190709bdd5353b" + "reference": "3b6463645c6766f78ce537c70cb4fdabee1e725f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-uri/zipball/fb998b9487ea8c5f4aaac0e536190709bdd5353b", - "reference": "fb998b9487ea8c5f4aaac0e536190709bdd5353b", + "url": "https://api.github.com/repos/zendframework/zend-uri/zipball/3b6463645c6766f78ce537c70cb4fdabee1e725f", + "reference": "3b6463645c6766f78ce537c70cb4fdabee1e725f", "shasum": "" }, "require": { "php": "^5.6 || ^7.0", "zendframework/zend-escaper": "^2.5", - "zendframework/zend-validator": "^2.5" + "zendframework/zend-validator": "^2.10" }, "require-dev": { - "phpunit/phpunit": "^6.2.1 || ^5.7.15", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4", "zendframework/zend-coding-standard": "~1.0.0" }, "type": "library", @@ -2209,13 +2315,13 @@ "license": [ "BSD-3-Clause" ], - "description": "a component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)", - "homepage": "https://github.com/zendframework/zend-uri", + "description": "A component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)", "keywords": [ + "ZendFramework", "uri", - "zf2" + "zf" ], - "time": "2018-04-10T17:08:10+00:00" + "time": "2018-04-30T13:40:08+00:00" }, { "name": "zendframework/zend-validator", diff --git a/src/File/RenameUpload.php b/src/File/RenameUpload.php index 17568eb3..517fa9e4 100644 --- a/src/File/RenameUpload.php +++ b/src/File/RenameUpload.php @@ -1,14 +1,15 @@ false, 'overwrite' => false, 'randomize' => false, + 'stream_file_factory' => null, + 'upload_file_factory' => null, ]; /** @@ -49,6 +52,25 @@ public function __construct($targetOrOptions = []) } } + /** + * @param StreamFactoryInterface $factory Factory to use to produce a PSR-7 + * stream with which to seed a PSR-7 UploadedFileInterface. + * @return self + */ + public function setStreamFactory(StreamFactoryInterface $factory) + { + $this->options['stream_file_factory'] = $factory; + return $this; + } + + /** + * @return null|StreamFactoryInterface + */ + public function getStreamFactory() + { + return $this->options['stream_file_factory']; + } + /** * @param string $target Target file path or directory * @return self @@ -72,6 +94,25 @@ public function getTarget() return $this->options['target']; } + /** + * @param UploadedFileFactoryInterface $factory Factory to use to produce + * filtered PSR-7 UploadedFileInterface instances. + * @return self + */ + public function setUploadFileFactory(UploadedFileFactoryInterface $factory) + { + $this->options['upload_file_factory'] = $factory; + return $this; + } + + /** + * @return null|UploadedFileFactoryInterface + */ + public function getUploadFileFactory() + { + return $this->options['upload_file_factory']; + } + /** * @param bool $flag When true, this filter will use the $_FILES['name'] * as the target filename. @@ -153,55 +194,37 @@ public function getRandomize() * Renames the file $value to the new name set before * Returns the file $value, removing all but digit characters * - * @param string|array $value Full path of file to change or $_FILES data array + * @param string|array|UploadedFileInterface $value Full path of file to + * change; $_FILES data array; or UploadedFileInterface instance. + * @return string|array|UploadedFileInterface Returns one of the following: + * - New filename, for string $value + * - Array with tmp_name and name keys for array $value + * - UploadedFileInterface for UploadedFileInterface $value * @throws Exception\RuntimeException - * @return string|array The new filename which has been set, or false when there were errors */ public function filter($value) { - if (! is_scalar($value) && ! is_array($value)) { + if (! is_scalar($value) && ! is_array($value) && ! $value instanceof UploadedFileInterface) { return $value; } - // An uploaded file? Retrieve the 'tmp_name' - $isFileUpload = false; - if (is_array($value)) { - if (! isset($value['tmp_name'])) { - return $value; - } - - $isFileUpload = true; - $uploadData = $value; - $sourceFile = $value['tmp_name']; - } else { - $uploadData = [ - 'tmp_name' => $value, - 'name' => $value, - ]; - $sourceFile = $value; - } - - if (isset($this->alreadyFiltered[$sourceFile])) { - return $this->alreadyFiltered[$sourceFile]; + // PSR-7 uploaded file + if ($value instanceof UploadedFileInterface) { + return $this->filterPsr7UploadedFile($value); } - $targetFile = $this->getFinalTarget($uploadData); - if (! file_exists($sourceFile) || $sourceFile == $targetFile) { - return $value; + // File upload via traditional SAPI + if (is_array($value) && isset($value['tmp_name'])) { + return $this->filterSapiUploadedFile($value); } - $this->checkFileExists($targetFile); - $this->moveUploadedFile($sourceFile, $targetFile); - - $return = $targetFile; - if ($isFileUpload) { - $return = $uploadData; - $return['tmp_name'] = $targetFile; + // String filename + if (is_string($value)) { + return $this->filterStringFilename($value); } - $this->alreadyFiltered[$sourceFile] = $return; - - return $return; + // Unrecognized; return verbatim + return $value; } /** @@ -228,30 +251,34 @@ protected function moveUploadedFile($sourceFile, $targetFile) /** * @param string $targetFile Target file path + * @return void * @throws Exception\InvalidArgumentException */ protected function checkFileExists($targetFile) { - if (file_exists($targetFile)) { - if ($this->getOverwrite()) { - unlink($targetFile); - } else { - throw new Exception\InvalidArgumentException( - sprintf("File '%s' could not be renamed. It already exists.", $targetFile) - ); - } + if (! file_exists($targetFile)) { + return; + } + + if (! $this->getOverwrite()) { + throw new Exception\InvalidArgumentException( + sprintf("File '%s' could not be renamed. It already exists.", $targetFile) + ); } + + unlink($targetFile); } /** - * @param array $uploadData $_FILES array + * @param $source + * @param $clientFileName + * * @return string */ - protected function getFinalTarget($uploadData) + protected function getFinalTarget($source, $clientFileName) { - $source = $uploadData['tmp_name']; $target = $this->getTarget(); - if (! isset($target) || $target == '*') { + if ($target === null || $target === '*') { $target = $source; } @@ -259,7 +286,7 @@ protected function getFinalTarget($uploadData) if (is_dir($target)) { $targetDir = $target; $last = $target[strlen($target) - 1]; - if (($last != '/') && ($last != '\\')) { + if (($last !== '/') && ($last !== '\\')) { $targetDir .= DIRECTORY_SEPARATOR; } } else { @@ -269,12 +296,12 @@ protected function getFinalTarget($uploadData) // Get the target filename if ($this->getUseUploadName()) { - $targetFile = basename($uploadData['name']); + $targetFile = basename($clientFileName); } elseif (! is_dir($target)) { $targetFile = basename($target); if ($this->getUseUploadExtension() && ! $this->getRandomize()) { $targetInfo = pathinfo($targetFile); - $sourceinfo = pathinfo($uploadData['name']); + $sourceinfo = pathinfo($clientFileName); if (isset($sourceinfo['extension'])) { $targetFile = $targetInfo['filename'] . '.' . $sourceinfo['extension']; } @@ -284,7 +311,7 @@ protected function getFinalTarget($uploadData) } if ($this->getRandomize()) { - $targetFile = $this->applyRandomToFilename($uploadData['name'], $targetFile); + $targetFile = $this->applyRandomToFilename($clientFileName, $targetFile); } return $targetDir . $targetFile; @@ -311,4 +338,113 @@ protected function applyRandomToFilename($source, $filename) return $filename . $extension; } + + /** + * @param string $fileName + * @return string + */ + private function filterStringFilename($fileName) + { + if (isset($this->alreadyFiltered[$fileName])) { + return $this->alreadyFiltered[$fileName]; + } + + $targetFile = $this->getFinalTarget($fileName, $fileName); + if ($fileName === $targetFile || ! file_exists($fileName)) { + return $fileName; + } + + $this->checkFileExists($targetFile); + $this->moveUploadedFile($fileName, $targetFile); + $this->alreadyFiltered[$fileName] = $targetFile; + + return $this->alreadyFiltered[$fileName]; + } + + /** + * @param array $fileData + * @return array + */ + private function filterSapiUploadedFile(array $fileData) + { + $sourceFile = $fileData['tmp_name']; + + if (isset($this->alreadyFiltered[$sourceFile])) { + return $this->alreadyFiltered[$sourceFile]; + } + + $clientFilename = $fileData['name']; + + $targetFile = $this->getFinalTarget($sourceFile, $clientFilename); + if ($sourceFile === $targetFile || ! file_exists($sourceFile)) { + return $value; + } + + $this->checkFileExists($targetFile); + $this->moveUploadedFile($sourceFile, $targetFile); + + $this->alreadyFiltered[$sourceFile] = [ + 'tmp_name' => $clientFilename, + 'name' => $targetFile, + ]; + + return $this->alreadyFiltered[$sourceFile]; + } + + /** + * @param UploadedFileInterface $uploadedFile + * @return UploadedFileInterface + * @throws Exception\RuntimeException if no stream factory is composed in the filter. + * @throws Exception\RuntimeException if no uploaded file factory is composed in the filter. + */ + private function filterPsr7UploadedFile(UploadedFileInterface $uploadedFile) + { + $sourceFile = $uploadedFile->getStream()->getMetadata('uri'); + + if (isset($this->alreadyFiltered[$sourceFile])) { + return $this->alreadyFiltered[$sourceFile]; + } + + $clientFilename = $uploadedFile->getClientFilename(); + $targetFile = $this->getFinalTarget($sourceFile, $clientFilename); + + if ($sourceFile === $targetFile || ! file_exists($sourceFile)) { + return $uploadedFile; + } + + $this->checkFileExists($targetFile); + $uploadedFile->moveTo($targetFile); + + $streamFactory = $this->getStreamFactory(); + if (! $streamFactory) { + throw new Exception\RuntimeException(sprintf( + 'No PSR-17 %s present; cannot filter file. Please pass the stream_file_factory' + . ' option with a %s instance when creating the filter for use with PSR-7.', + StreamFactoryInterface::class, + StreamFactoryInterface::class + )); + } + + $stream = $streamFactory->createStreamFromFile($targetFile); + + $uploadedFileFactory = $this->getUploadFileFactory(); + if (! $uploadedFileFactory) { + throw new Exception\RuntimeException(sprintf( + 'No PSR-17 %s present; cannot filter file. Please pass the upload_file_factory' + . ' option with a %s instance when creating the filter for use with PSR-7.', + UploadedFileFactoryInterface::class, + UploadedFileFactoryInterface::class + )); + } + + $this->alreadyFiltered[$sourceFile] = $uploadedFileFactory->createUploadedFile( + $stream, + filesize($targetFile), + UPLOAD_ERR_OK, + $uploadedFile->getClientFilename(), + $uploadedFile->getClientMediaType() + ); + + return $this->alreadyFiltered[$sourceFile]; + } } diff --git a/test/File/RenameUploadTest.php b/test/File/RenameUploadTest.php index 8532b1e5..bf462611 100644 --- a/test/File/RenameUploadTest.php +++ b/test/File/RenameUploadTest.php @@ -1,15 +1,18 @@ assertEquals('falsefile', $filter('falsefile')); } + /** + * @requires PHP 7 + * @return void + */ + public function testStringConstructorWithPsrFile() + { + $sourceFile = $this->sourceFile; + $targetFile = $this->targetFile; + + $originalStream = $this->prophesize(StreamInterface::class); + $originalStream->getMetadata('uri')->willReturn($this->sourceFile); + + $originalFile = $this->prophesize(UploadedFileInterface::class); + $originalFile->getStream()->will([$originalStream, 'reveal']); + $originalFile->getClientFilename()->willReturn($targetFile); + $originalFile + ->moveTo($targetFile) + ->will(function ($args) use ($sourceFile) { + $targetFile = array_shift($args); + copy($sourceFile, $targetFile); + }) + ->shouldBeCalled(); + $originalFile->getClientMediaType()->willReturn(null); + + $renamedStream = $this->prophesize(StreamInterface::class); + $streamFactory = $this->prophesize(StreamFactoryInterface::class); + $streamFactory + ->createStreamFromFile($targetFile) + ->will([$renamedStream, 'reveal']); + + $renamedFile = $this->prophesize(UploadedFileInterface::class); + + $fileFactory = $this->prophesize(UploadedFileFactoryInterface::class); + $fileFactory + ->createUploadedFile( + Argument::that([$renamedStream, 'reveal']), + 0, // we can hardcode this, as we know the file is empty + UPLOAD_ERR_OK, + $targetFile, + null + ) + ->will([$renamedFile, 'reveal']); + + $filter = new RenameUploadMock($targetFile); + $this->assertEquals($targetFile, $filter->getTarget()); + + $filter->setStreamFactory($streamFactory->reveal()); + $filter->setUploadFileFactory($fileFactory->reveal()); + + $moved = $filter($originalFile->reveal()); + + $this->assertSame($renamedFile->reveal(), $moved); + } + /** * @return void */