From 993eecc5126594a09ca39f206e200144bfb4a687 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 8 Apr 2015 15:44:43 +0200 Subject: [PATCH 01/51] Removed invalid exclude in phpunit.xml.dist Signed-off-by: Tom Van Herreweghe --- phpunit.xml.dist | 1 - 1 file changed, 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7470936..8ef93dc 100755 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -13,7 +13,6 @@ ./lib - ./autoload.php *Interface.php From 54fff2b6e99f7ae4f3bf5ba03f701486eb751ab6 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 9 Apr 2015 13:38:49 +0200 Subject: [PATCH 02/51] Cleanup of composer.json & lock file Signed-off-by: Tom Van Herreweghe --- composer.json | 9 +- composer.lock | 1049 +++++++++++++++++++++++++++---------------------- 2 files changed, 593 insertions(+), 465 deletions(-) diff --git a/composer.json b/composer.json index d0710d3..9dd2ee3 100755 --- a/composer.json +++ b/composer.json @@ -15,18 +15,17 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*", + "phpunit/phpunit": "~4.5.0", "satooshi/php-coveralls": "~0.6", - "phpmd/phpmd": "~2.2", - "sebastian/phpcpd": "1.4.*@stable", - "squizlabs/php_codesniffer": "1.4.*@stable" + "phpmd/phpmd": "~2.2.0" }, "suggest": { "lib-exiftool": "Use perl lib exiftool as adapter" }, + "minimum-stability": "dev", "autoload": { "psr-0": { "PHPExif": "lib/" } } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 499bdee..55313fe 100644 --- a/composer.lock +++ b/composer.lock @@ -4,12 +4,66 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1eb0d80e545f6ba06a71ff8a967d3c2e", + "hash": "506544b0b2fb13a1c72e8f53d25cb6be", "packages": [], "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "3d9669e597439e8d205baf315efb757038fb4dea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/3d9669e597439e8d205baf315efb757038fb4dea", + "reference": "3d9669e597439e8d205baf315efb757038fb4dea", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-01-16 19:29:51" + }, { "name": "guzzle/guzzle", - "version": "v3.9.3", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle3.git", @@ -141,6 +195,56 @@ "description": "Official version of pdepend to be handled with Composer", "time": "2015-03-02 08:06:43" }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d1da796ba5565789a623052eb9f2cf59d57fec60" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d1da796ba5565789a623052eb9f2cf59d57fec60", + "reference": "d1da796ba5565789a623052eb9f2cf59d57fec60", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0", + "league/commonmark": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-27 09:28:18" + }, { "name": "phpmd/phpmd", "version": "2.2.2", @@ -203,48 +307,109 @@ ], "time": "2015-03-26 07:47:05" }, + { + "name": "phpspec/prophecy", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", + "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-03-27 19:31:25" + }, { "name": "phpunit/php-code-coverage", - "version": "1.2.18", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" + "reference": "e28bf7a678fa669f77933de56cb85f3ae36358c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e28bf7a678fa669f77933de56cb85f3ae36358c3", + "reference": "e28bf7a678fa669f77933de56cb85f3ae36358c3", "shasum": "" }, "require": { "php": ">=5.3.3", - "phpunit/php-file-iterator": ">=1.3.0@stable", - "phpunit/php-text-template": ">=1.2.0@stable", - "phpunit/php-token-stream": ">=1.1.3,<1.3.0" + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "~1.0", + "sebastian/version": "~1.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*@dev" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.0.5" + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -262,7 +427,7 @@ "testing", "xunit" ], - "time": "2014-09-02 10:13:14" + "time": "2015-04-09 09:55:28" }, { "name": "phpunit/php-file-iterator", @@ -359,12 +524,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1.0.5" + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1.0.5", - "reference": "1.0.5", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", "shasum": "" }, "require": { @@ -399,45 +564,44 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.2.2", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" + "reference": "eab81d02569310739373308137284e0158424330" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", + "reference": "eab81d02569310739373308137284e0158424330", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], "description": "Wrapper around PHP's tokenizer extension.", @@ -445,62 +609,61 @@ "keywords": [ "tokenizer" ], - "time": "2014-03-03 05:10:30" + "time": "2015-04-08 04:46:07" }, { "name": "phpunit/phpunit", - "version": "3.7.38", + "version": "4.5.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" + "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d6429b0995b24a2d9dfe5587ee3a7071c1161af4", + "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-dom": "*", "ext-json": "*", "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpunit/php-code-coverage": "~1.2", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.1", - "phpunit/php-timer": "~1.0", - "phpunit/phpunit-mock-objects": "~1.2", + "phpspec/prophecy": "~1.3,>=1.3.1", + "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpunit/php-file-iterator": "~1.3.2", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "~1.0.2", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.1", + "sebastian/environment": "~1.2", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", "symfony/yaml": "~2.0" }, - "require-dev": { - "pear-pear.php.net/pear": "1.9.4" - }, "suggest": { "phpunit/php-invoker": "~1.1" }, "bin": [ - "composer/bin/phpunit" + "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.7.x-dev" + "dev-master": "4.5.x-dev" } }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], "license": [ "BSD-3-Clause" ], @@ -512,45 +675,51 @@ } ], "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], - "time": "2014-10-17 09:04:17" + "time": "2015-03-29 09:24:05" }, { "name": "phpunit/phpunit-mock-objects", - "version": "1.2.3", + "version": "dev-master", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "1.2.3" + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip", - "reference": "1.2.3", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", + "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", "shasum": "" }, "require": { + "doctrine/instantiator": "~1.0,>=1.0.2", "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" + "phpunit/php-text-template": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" }, "suggest": { "ext-soap": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -567,20 +736,20 @@ "mock", "xunit" ], - "time": "2013-01-13 10:24:48" + "time": "2015-04-02 05:36:41" }, { "name": "psr/log", "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log", - "reference": "1.0.0" + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" }, "dist": { "type": "zip", - "url": "https://github.com/php-fig/log/archive/1.0.0.zip", - "reference": "1.0.0", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", "shasum": "" }, "type": "library", @@ -609,23 +778,22 @@ }, { "name": "satooshi/php-coveralls", - "version": "v0.6.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "v0.6.1" + "reference": "2fbf803803d179ab1082807308a67bbd5a760c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/v0.6.1", - "reference": "v0.6.1", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/2fbf803803d179ab1082807308a67bbd5a760c70", + "reference": "2fbf803803d179ab1082807308a67bbd5a760c70", "shasum": "" }, "require": { - "ext-curl": "*", "ext-json": "*", "ext-simplexml": "*", - "guzzle/guzzle": ">=3.0", + "guzzle/guzzle": ">=2.7", "php": ">=5.3", "psr/log": "1.0.0", "symfony/config": ">=2.0", @@ -635,7 +803,7 @@ }, "require-dev": { "apigen/apigen": "2.8.*@stable", - "pdepend/pdepend": "dev-master", + "pdepend/pdepend": "dev-master as 2.0.0", "phpmd/phpmd": "dev-master", "phpunit/php-invoker": ">=1.1.0,<1.2.0", "phpunit/phpunit": "3.7.*@stable", @@ -644,14 +812,22 @@ "squizlabs/php_codesniffer": "1.4.*@stable", "theseer/fdomdocument": "dev-master" }, + "suggest": { + "symfony/http-kernel": "Allows Symfony integration" + }, "bin": [ "composer/bin/coveralls" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.7-dev" + } + }, "autoload": { "psr-0": { - "Contrib\\Component": "src/", - "Contrib\\Bundle": "src/" + "Satooshi\\Component": "src/", + "Satooshi\\Bundle": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -673,27 +849,36 @@ "github", "test" ], - "time": "2013-05-04 08:07:33" + "time": "2014-11-11 15:35:34" }, { - "name": "sebastian/finder-facade", - "version": "1.1.0", + "name": "sebastian/comparator", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/finder-facade.git", - "reference": "1.1.0" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/1.1.0", - "reference": "1.1.0", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", "shasum": "" }, "require": { - "symfony/finder": ">=2.2.0", - "theseer/fdomdocument": ">=1.3.1" + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -704,44 +889,110 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", - "homepage": "https://github.com/sebastianbergmann/finder-facade", - "time": "2013-05-28 06:10:03" + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-01-29 16:28:08" }, { - "name": "sebastian/phpcpd", - "version": "1.4.3", + "name": "sebastian/diff", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpcpd.git", - "reference": "1.4.3" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/1.4.3", - "reference": "1.4.3", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-timer": ">=1.0.4,<1.1.0", - "sebastian/finder-facade": "~1.1", - "sebastian/version": ">=1.0.0", - "symfony/finder": ">=2.1.2", - "theseer/fdomdocument": "~1.4", - "zetacomponents/base": ">=1.8", - "zetacomponents/console-tools": ">=1.6" + "php": ">=5.3.3" }, - "bin": [ - "composer/bin/phpcpd" + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-02-22 15:13:53" + }, + { + "name": "sebastian/environment", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -754,29 +1005,45 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Copy/Paste Detector (CPD) for PHP code.", - "homepage": "https://github.com/sebastianbergmann/phpcpd", - "time": "2013-07-30 14:37:42" + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-01-01 10:01:08" }, { - "name": "sebastian/version", - "version": "1.0.4", + "name": "sebastian/exporter", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "84839970d05254c73cde183a721c7af13aede943" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", + "reference": "84839970d05254c73cde183a721c7af13aede943", "shasum": "" }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -787,67 +1054,67 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2014-12-15 14:25:24" + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-01-27 07:23:06" }, { - "name": "squizlabs/php_codesniffer", - "version": "1.4.8", + "name": "sebastian/global-state", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d26daa8096ad2c8758677f0352597f8cda4722e0" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "007c441df427cf0e175372fcbb9d196bce7eb743" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d26daa8096ad2c8758677f0352597f8cda4722e0", - "reference": "d26daa8096ad2c8758677f0352597f8cda4722e0", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/007c441df427cf0e175372fcbb9d196bce7eb743", + "reference": "007c441df427cf0e175372fcbb9d196bce7eb743", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=5.1.2" + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" }, "suggest": { - "phpunit/php-timer": "dev-master" + "ext-uopz": "*" }, - "bin": [ - "scripts/phpcs" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/MultiFileSniff.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/CommentParser/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -856,44 +1123,131 @@ ], "authors": [ { - "name": "Greg Sherwood", - "role": "lead" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ - "phpcs", - "standards" + "global state" + ], + "time": "2015-01-20 04:09:31" + }, + { + "name": "sebastian/recursion-context", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-01-24 09:48:32" + }, + { + "name": "sebastian/version", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } ], - "time": "2013-11-25 22:07:04" + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-02-24 06:35:25" }, { "name": "symfony/config", - "version": "v2.6.5", + "version": "dev-master", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "7a47189c7667ca69bcaafd19ef8a8941db449a2c" + "reference": "631c3190d7fc8fe17094057867928c24bf6b9683" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/7a47189c7667ca69bcaafd19ef8a8941db449a2c", - "reference": "7a47189c7667ca69bcaafd19ef8a8941db449a2c", + "url": "https://api.github.com/repos/symfony/Config/zipball/631c3190d7fc8fe17094057867928c24bf6b9683", + "reference": "631c3190d7fc8fe17094057867928c24bf6b9683", "shasum": "" }, "require": { - "php": ">=5.3.3", - "symfony/filesystem": "~2.3" + "php": ">=5.5.9", + "symfony/filesystem": "~2.7|~3.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~2.7|~3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -917,31 +1271,31 @@ ], "description": "Symfony Config Component", "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" + "time": "2015-04-08 05:30:14" }, { "name": "symfony/console", - "version": "v2.6.5", + "version": "dev-master", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "53f86497ccd01677e22435cfb7262599450a90d1" + "reference": "db3fa7b6c97abc09fa4e2b5be3f0e700469e589f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/53f86497ccd01677e22435cfb7262599450a90d1", - "reference": "53f86497ccd01677e22435cfb7262599450a90d1", + "url": "https://api.github.com/repos/symfony/Console/zipball/db3fa7b6c97abc09fa4e2b5be3f0e700469e589f", + "reference": "db3fa7b6c97abc09fa4e2b5be3f0e700469e589f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9" }, "require-dev": { "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.1" + "symfony/event-dispatcher": "~2.7|~3.0", + "symfony/phpunit-bridge": "~2.7|~3.0", + "symfony/process": "~2.7|~3.0" }, "suggest": { "psr/log": "For using the console logger", @@ -951,7 +1305,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -975,34 +1329,31 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2015-03-13 17:37:22" + "time": "2015-04-08 05:30:14" }, { "name": "symfony/dependency-injection", - "version": "v2.6.5", + "version": "dev-master", "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "a49245b2beebe332924561c30772b16e1d32f13a" + "reference": "4d12bccee943457b8999dcf83c31f62971173c20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/a49245b2beebe332924561c30772b16e1d32f13a", - "reference": "a49245b2beebe332924561c30772b16e1d32f13a", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/4d12bccee943457b8999dcf83c31f62971173c20", + "reference": "4d12bccee943457b8999dcf83c31f62971173c20", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "conflict": { - "symfony/expression-language": "<2.6" + "php": ">=5.5.9" }, "require-dev": { - "symfony/config": "~2.2", - "symfony/expression-language": "~2.6", - "symfony/phpunit-bridge": "~2.7", - "symfony/yaml": "~2.1" + "symfony/config": "~2.7|~3.0", + "symfony/expression-language": "~2.7|~3.0", + "symfony/phpunit-bridge": "~2.7|~3.0", + "symfony/yaml": "~2.7|~3.0" }, "suggest": { "symfony/config": "", @@ -1012,7 +1363,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1036,33 +1387,33 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "http://symfony.com", - "time": "2015-03-17 12:44:40" + "time": "2015-03-30 15:59:03" }, { "name": "symfony/event-dispatcher", - "version": "v2.6.5", + "version": "2.7.x-dev", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284" + "reference": "186349c2966529804e38685f671e64746dde220b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/70f7c8478739ad21e3deef0d977b38c77f1fb284", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/186349c2966529804e38685f671e64746dde220b", + "reference": "186349c2966529804e38685f671e64746dde220b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5", - "symfony/dependency-injection": "~2.6", - "symfony/expression-language": "~2.6", - "symfony/phpunit-bridge": "~2.7", - "symfony/stopwatch": "~2.3" + "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/phpunit-bridge": "~2.7|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" }, "suggest": { "symfony/dependency-injection": "", @@ -1071,7 +1422,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { @@ -1095,33 +1446,33 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2015-03-13 17:37:22" + "time": "2015-03-13 17:50:01" }, { "name": "symfony/filesystem", - "version": "v2.6.5", + "version": "dev-master", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "fdc5f151bc2db066b51870d5bea3773d915ced0b" + "reference": "afb9d158555bee3441dc5c1e68d9c35d332543eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/fdc5f151bc2db066b51870d5bea3773d915ced0b", - "reference": "fdc5f151bc2db066b51870d5bea3773d915ced0b", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/afb9d158555bee3441dc5c1e68d9c35d332543eb", + "reference": "afb9d158555bee3441dc5c1e68d9c35d332543eb", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~2.7|~3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1145,83 +1496,33 @@ ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" - }, - { - "name": "symfony/finder", - "version": "v2.6.5", - "target-dir": "Symfony/Component/Finder", - "source": { - "type": "git", - "url": "https://github.com/symfony/Finder.git", - "reference": "bebc7479c566fa4f14b9bcef9e32e719eabec74e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/bebc7479c566fa4f14b9bcef9e32e719eabec74e", - "reference": "bebc7479c566fa4f14b9bcef9e32e719eabec74e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Finder\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Finder Component", - "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" + "time": "2015-03-24 17:09:17" }, { "name": "symfony/stopwatch", - "version": "v2.6.5", + "version": "dev-master", "target-dir": "Symfony/Component/Stopwatch", "source": { "type": "git", "url": "https://github.com/symfony/Stopwatch.git", - "reference": "ba4e774f71e2ce3e3f65cabac4031b9029972af5" + "reference": "bae98f9404e96f48e5e89f2fd3bb3f2dce52e431" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/ba4e774f71e2ce3e3f65cabac4031b9029972af5", - "reference": "ba4e774f71e2ce3e3f65cabac4031b9029972af5", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/bae98f9404e96f48e5e89f2fd3bb3f2dce52e431", + "reference": "bae98f9404e96f48e5e89f2fd3bb3f2dce52e431", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~2.7|~3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1245,33 +1546,33 @@ ], "description": "Symfony Stopwatch Component", "homepage": "http://symfony.com", - "time": "2015-02-24 11:52:21" + "time": "2015-03-24 17:09:17" }, { "name": "symfony/yaml", - "version": "v2.6.5", + "version": "2.7.x-dev", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "0cd8e72071e46e15fc072270ae39ea1b66b10a9d" + "reference": "3882af2f22672e347030b561cc6c5abc2b335566" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/0cd8e72071e46e15fc072270ae39ea1b66b10a9d", - "reference": "0cd8e72071e46e15fc072270ae39ea1b66b10a9d", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/3882af2f22672e347030b561cc6c5abc2b335566", + "reference": "3882af2f22672e347030b561cc6c5abc2b335566", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~2.7|~3.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { @@ -1295,184 +1596,12 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" - }, - { - "name": "theseer/fdomdocument", - "version": "1.6.0", - "source": { - "type": "git", - "url": "https://github.com/theseer/fDOMDocument.git", - "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d08cf070350f884c63fc9078d27893c2ab6c7cef", - "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "lib-libxml": "*", - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "lead" - } - ], - "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", - "homepage": "https://github.com/theseer/fDOMDocument", - "time": "2014-09-13 10:57:19" - }, - { - "name": "zetacomponents/base", - "version": "1.9", - "source": { - "type": "git", - "url": "https://github.com/zetacomponents/Base.git", - "reference": "f20df24e8de3e48b6b69b2503f917e457281e687" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zetacomponents/Base/zipball/f20df24e8de3e48b6b69b2503f917e457281e687", - "reference": "f20df24e8de3e48b6b69b2503f917e457281e687", - "shasum": "" - }, - "require-dev": { - "zetacomponents/unit-test": "*" - }, - "type": "library", - "autoload": { - "classmap": [ - "src" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Sergey Alexeev" - }, - { - "name": "Sebastian Bergmann" - }, - { - "name": "Jan Borsodi" - }, - { - "name": "Raymond Bosman" - }, - { - "name": "Frederik Holljen" - }, - { - "name": "Kore Nordmann" - }, - { - "name": "Derick Rethans" - }, - { - "name": "Vadym Savchuk" - }, - { - "name": "Tobias Schlitt" - }, - { - "name": "Alexandru Stanoi" - } - ], - "description": "The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.", - "homepage": "https://github.com/zetacomponents", - "time": "2014-09-19 03:28:34" - }, - { - "name": "zetacomponents/console-tools", - "version": "1.7", - "source": { - "type": "git", - "url": "https://github.com/zetacomponents/ConsoleTools.git", - "reference": "30d67e9d04f458ac8cae4c49e50f81061460ff2c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zetacomponents/ConsoleTools/zipball/30d67e9d04f458ac8cae4c49e50f81061460ff2c", - "reference": "30d67e9d04f458ac8cae4c49e50f81061460ff2c", - "shasum": "" - }, - "require": { - "zetacomponents/base": "~1.8" - }, - "require-dev": { - "zetacomponents/unit-test": "*" - }, - "type": "library", - "autoload": { - "classmap": [ - "src" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Sergey Alexeev" - }, - { - "name": "Sebastian Bergmann" - }, - { - "name": "Jan Borsodi" - }, - { - "name": "Raymond Bosman" - }, - { - "name": "Frederik Holljen" - }, - { - "name": "Kore Nordmann" - }, - { - "name": "Derick Rethans" - }, - { - "name": "Vadym Savchuk" - }, - { - "name": "Tobias Schlitt" - }, - { - "name": "Alexandru Stanoi" - } - ], - "description": "A set of classes to do different actions with the console (also called shell). It can render a progress bar, tables and a status bar and contains a class for parsing command line options.", - "homepage": "https://github.com/zetacomponents", - "time": "2014-09-27 19:26:09" + "time": "2015-03-30 15:55:07" } ], "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "sebastian/phpcpd": 0, - "squizlabs/php_codesniffer": 0 - }, + "minimum-stability": "dev", + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From de5f518eff70baeac28179b4b9f3ccdef30688cd Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 4 Dec 2015 20:38:03 +0100 Subject: [PATCH 03/51] Tabula rasa & re-implemented most things Signed-off-by: Tom Van Herreweghe --- .coveralls.yml | 1 - .travis.yml | 30 - CHANGELOG.rst | 5 + Resources/doc/usage.md | 32 - Resources/doc/usage_0.2.1.md | 32 - composer.json | 9 +- composer.lock | 1611 ----------------- grumphp.yml | 21 + lib/PHPExif/Adapter/AdapterAbstract.php | 132 -- lib/PHPExif/Adapter/AdapterInterface.php | 33 - lib/PHPExif/Adapter/Exiftool.php | 161 -- lib/PHPExif/Adapter/Native.php | 239 --- lib/PHPExif/Exif.php | 843 --------- lib/PHPExif/Hydrator/HydratorInterface.php | 33 - lib/PHPExif/Hydrator/Mutator.php | 56 - lib/PHPExif/Mapper/Exiftool.php | 210 --- lib/PHPExif/Mapper/Native.php | 254 --- lib/PHPExif/Reader/Reader.php | 111 -- lib/PHPExif/Reader/ReaderInterface.php | 33 - .../PHPExif/Adapter}/MapperInterface.php | 20 +- .../Adapter/Native/Reader/Configuration.php | 119 ++ src/PHPExif/Adapter/Native/Reader/Mapper.php | 379 ++++ src/PHPExif/Adapter/Native/Reader/Reader.php | 138 ++ src/PHPExif/Adapter/ReaderInterface.php | 33 + .../PHPExif/Data/Exif.php | 24 +- src/PHPExif/Data/ExifInterface.php | 50 + src/PHPExif/Data/Iptc.php | 266 +++ src/PHPExif/Data/IptcInterface.php | 151 ++ src/PHPExif/Exception/InteruptException.php | 22 + src/PHPExif/Exception/NoExifDataException.php | 37 + .../Exception/UnknownAdapterTypeException.php | 55 + src/PHPExif/Reader.php | 93 + tests/PHPExif/Adapter/AdapterAbstractTest.php | 232 --- .../PHPExif/Adapter/ExiftoolProcOpenTest.php | 68 - tests/PHPExif/Adapter/ExiftoolTest.php | 113 -- tests/PHPExif/Adapter/NativeTest.php | 185 -- tests/PHPExif/ExifTest.php | 639 ------- tests/PHPExif/Hydrator/MutatorTest.php | 69 - tests/PHPExif/Mapper/ExiftoolMapperTest.php | 296 --- tests/PHPExif/Mapper/NativeMapperTest.php | 284 --- tests/PHPExif/Reader/ReaderTest.php | 161 -- tests/PHPExif/ReaderTest.php | 56 + tests/files/dsc_5794.jpg | Bin 229970 -> 0 bytes tests/files/empty.jpg | 1 - tests/files/morning_glory_pool_500.jpg | Bin 266269 -> 0 bytes 45 files changed, 1458 insertions(+), 5879 deletions(-) delete mode 100644 .coveralls.yml delete mode 100755 .travis.yml delete mode 100644 Resources/doc/usage.md delete mode 100644 Resources/doc/usage_0.2.1.md delete mode 100644 composer.lock create mode 100644 grumphp.yml delete mode 100644 lib/PHPExif/Adapter/AdapterAbstract.php delete mode 100644 lib/PHPExif/Adapter/AdapterInterface.php delete mode 100644 lib/PHPExif/Adapter/Exiftool.php delete mode 100644 lib/PHPExif/Adapter/Native.php delete mode 100755 lib/PHPExif/Exif.php delete mode 100644 lib/PHPExif/Hydrator/HydratorInterface.php delete mode 100644 lib/PHPExif/Hydrator/Mutator.php delete mode 100644 lib/PHPExif/Mapper/Exiftool.php delete mode 100644 lib/PHPExif/Mapper/Native.php delete mode 100755 lib/PHPExif/Reader/Reader.php delete mode 100644 lib/PHPExif/Reader/ReaderInterface.php rename {lib/PHPExif/Mapper => src/PHPExif/Adapter}/MapperInterface.php (62%) create mode 100644 src/PHPExif/Adapter/Native/Reader/Configuration.php create mode 100644 src/PHPExif/Adapter/Native/Reader/Mapper.php create mode 100644 src/PHPExif/Adapter/Native/Reader/Reader.php create mode 100644 src/PHPExif/Adapter/ReaderInterface.php rename lib/PHPExif/Adapter/NoAdapterException.php => src/PHPExif/Data/Exif.php (50%) create mode 100644 src/PHPExif/Data/ExifInterface.php create mode 100644 src/PHPExif/Data/Iptc.php create mode 100644 src/PHPExif/Data/IptcInterface.php create mode 100644 src/PHPExif/Exception/InteruptException.php create mode 100644 src/PHPExif/Exception/NoExifDataException.php create mode 100644 src/PHPExif/Exception/UnknownAdapterTypeException.php create mode 100644 src/PHPExif/Reader.php delete mode 100644 tests/PHPExif/Adapter/AdapterAbstractTest.php delete mode 100644 tests/PHPExif/Adapter/ExiftoolProcOpenTest.php delete mode 100644 tests/PHPExif/Adapter/ExiftoolTest.php delete mode 100755 tests/PHPExif/Adapter/NativeTest.php delete mode 100755 tests/PHPExif/ExifTest.php delete mode 100644 tests/PHPExif/Hydrator/MutatorTest.php delete mode 100644 tests/PHPExif/Mapper/ExiftoolMapperTest.php delete mode 100644 tests/PHPExif/Mapper/NativeMapperTest.php delete mode 100644 tests/PHPExif/Reader/ReaderTest.php create mode 100644 tests/PHPExif/ReaderTest.php delete mode 100644 tests/files/dsc_5794.jpg delete mode 100644 tests/files/empty.jpg delete mode 100644 tests/files/morning_glory_pool_500.jpg diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index 6b74c21..0000000 --- a/.coveralls.yml +++ /dev/null @@ -1 +0,0 @@ -src_dir: lib diff --git a/.travis.yml b/.travis.yml deleted file mode 100755 index b6272df..0000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -language: php - -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - -matrix: - allow_failures: - - php: 5.6 - -script: - - mkdir -p build/logs - - php vendor/bin/phpunit -c phpunit.xml.dist - - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml - - ./vendor/bin/phpcs --standard=PSR2 ./lib/ - -before_script: - - composer install --prefer-source - -after_script: - - php vendor/bin/coveralls -v - -before_install: - - composer self-update - - wget http://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-9.90.tar.gz - - tar -zxvf Image-ExifTool-9.90.tar.gz - - cd Image-ExifTool-9.90 && perl Makefile.PL && make test && sudo make install - - cd .. && rm -rf Image-ExifTool-9.90 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2059618..c8fba32 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,11 @@ CHANGELOG ===== +1.0.0 +----- + +* PSR-4 compliant + 0.4.0 ----- diff --git a/Resources/doc/usage.md b/Resources/doc/usage.md deleted file mode 100644 index 20b0294..0000000 --- a/Resources/doc/usage.md +++ /dev/null @@ -1,32 +0,0 @@ -## Usage ## - -### Using factory method - -```php -read('/path/to/file'); - -echo 'Title: ' . $exif->getTitle() . PHP_EOL; -``` - -### Using custom options - -```php - '/path/to/exiftool', - ) -); -$reader = new \PHPExif\Reader\Reader($adapter); - -$exif = $reader->read('/path/to/file'); - -echo 'Title: ' . $exif->getTitle() . PHP_EOL; -``` \ No newline at end of file diff --git a/Resources/doc/usage_0.2.1.md b/Resources/doc/usage_0.2.1.md deleted file mode 100644 index 3cbbf10..0000000 --- a/Resources/doc/usage_0.2.1.md +++ /dev/null @@ -1,32 +0,0 @@ -## Usage ## - -### Using factory method - -```php -getExifFromFile('/path/to/file'); - -echo 'Title: ' . $exif->getTitle() . PHP_EOL; -``` - -### Using custom options - -```php - '/path/to/exiftool', - ) -); -$reader = new \PHPExif\Reader($adapter); - -$exif = $reader->getExifFromFile('/path/to/file'); - -echo 'Title: ' . $exif->getTitle() . PHP_EOL; -``` \ No newline at end of file diff --git a/composer.json b/composer.json index 9dd2ee3..edd40fe 100755 --- a/composer.json +++ b/composer.json @@ -15,17 +15,16 @@ "php": ">=5.3.0" }, "require-dev": { + "phpmd/phpmd": "~2.2.0", + "phpro/grumphp": "~0.1", "phpunit/phpunit": "~4.5.0", - "satooshi/php-coveralls": "~0.6", - "phpmd/phpmd": "~2.2.0" + "satooshi/php-coveralls": "~0.6" }, "suggest": { "lib-exiftool": "Use perl lib exiftool as adapter" }, "minimum-stability": "dev", "autoload": { - "psr-0": { - "PHPExif": "lib/" - } + "psr-4": { "PHPExif\\": "src/" } } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 55313fe..0000000 --- a/composer.lock +++ /dev/null @@ -1,1611 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "hash": "506544b0b2fb13a1c72e8f53d25cb6be", - "packages": [], - "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "3d9669e597439e8d205baf315efb757038fb4dea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/3d9669e597439e8d205baf315efb757038fb4dea", - "reference": "3d9669e597439e8d205baf315efb757038fb4dea", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-01-16 19:29:51" - }, - { - "name": "guzzle/guzzle", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle3.git", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.3.3", - "symfony/event-dispatcher": "~2.1" - }, - "replace": { - "guzzle/batch": "self.version", - "guzzle/cache": "self.version", - "guzzle/common": "self.version", - "guzzle/http": "self.version", - "guzzle/inflection": "self.version", - "guzzle/iterator": "self.version", - "guzzle/log": "self.version", - "guzzle/parser": "self.version", - "guzzle/plugin": "self.version", - "guzzle/plugin-async": "self.version", - "guzzle/plugin-backoff": "self.version", - "guzzle/plugin-cache": "self.version", - "guzzle/plugin-cookie": "self.version", - "guzzle/plugin-curlauth": "self.version", - "guzzle/plugin-error-response": "self.version", - "guzzle/plugin-history": "self.version", - "guzzle/plugin-log": "self.version", - "guzzle/plugin-md5": "self.version", - "guzzle/plugin-mock": "self.version", - "guzzle/plugin-oauth": "self.version", - "guzzle/service": "self.version", - "guzzle/stream": "self.version" - }, - "require-dev": { - "doctrine/cache": "~1.3", - "monolog/monolog": "~1.0", - "phpunit/phpunit": "3.7.*", - "psr/log": "~1.0", - "symfony/class-loader": "~2.1", - "zendframework/zend-cache": "2.*,<2.3", - "zendframework/zend-log": "2.*,<2.3" - }, - "suggest": { - "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.9-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle": "src/", - "Guzzle\\Tests": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Guzzle Community", - "homepage": "https://github.com/guzzle/guzzle/contributors" - } - ], - "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2015-03-18 18:23:50" - }, - { - "name": "pdepend/pdepend", - "version": "2.0.6", - "source": { - "type": "git", - "url": "https://github.com/pdepend/pdepend.git", - "reference": "a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4", - "reference": "a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4", - "shasum": "" - }, - "require": { - "symfony/config": ">=2.4", - "symfony/dependency-injection": ">=2.4", - "symfony/filesystem": ">=2.4" - }, - "require-dev": { - "phpunit/phpunit": "4.*@stable", - "squizlabs/php_codesniffer": "@stable" - }, - "bin": [ - "src/bin/pdepend" - ], - "type": "library", - "autoload": { - "psr-0": { - "PDepend\\": "src/main/php/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Official version of pdepend to be handled with Composer", - "time": "2015-03-02 08:06:43" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d1da796ba5565789a623052eb9f2cf59d57fec60" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d1da796ba5565789a623052eb9f2cf59d57fec60", - "reference": "d1da796ba5565789a623052eb9f2cf59d57fec60", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0", - "league/commonmark": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "phpDocumentor": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" - } - ], - "time": "2015-02-27 09:28:18" - }, - { - "name": "phpmd/phpmd", - "version": "2.2.2", - "source": { - "type": "git", - "url": "https://github.com/phpmd/phpmd.git", - "reference": "7dc4a6b5c07b119ab5da7960b56303fa6855eb84" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/7dc4a6b5c07b119ab5da7960b56303fa6855eb84", - "reference": "7dc4a6b5c07b119ab5da7960b56303fa6855eb84", - "shasum": "" - }, - "require": { - "pdepend/pdepend": "2.0.*", - "php": ">=5.3.0", - "symfony/config": ">=2.4", - "symfony/dependency-injection": ">=2.4", - "symfony/filesystem": ">=2.4" - }, - "require-dev": { - "phpunit/phpunit": "*", - "squizlabs/php_codesniffer": "*" - }, - "bin": [ - "src/bin/phpmd" - ], - "type": "project", - "autoload": { - "psr-0": { - "PHPMD\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Manuel Pichler", - "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler", - "role": "Project founder" - }, - { - "name": "Other contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", - "role": "Contributors" - } - ], - "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", - "homepage": "http://phpmd.org/", - "keywords": [ - "mess detection", - "mess detector", - "pdepend", - "phpmd", - "pmd" - ], - "time": "2015-03-26 07:47:05" - }, - { - "name": "phpspec/prophecy", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", - "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1" - }, - "require-dev": { - "phpspec/phpspec": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2015-03-27 19:31:25" - }, - { - "name": "phpunit/php-code-coverage", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "e28bf7a678fa669f77933de56cb85f3ae36358c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e28bf7a678fa669f77933de56cb85f3ae36358c3", - "reference": "e28bf7a678fa669f77933de56cb85f3ae36358c3", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "~1.0", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-04-09 09:55:28" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.3.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "File/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2013-10-10 15:34:57" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "Text/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2014-01-30 17:20:04" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2013-08-02 07:42:54" - }, - { - "name": "phpunit/php-token-stream", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "eab81d02569310739373308137284e0158424330" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", - "reference": "eab81d02569310739373308137284e0158424330", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2015-04-08 04:46:07" - }, - { - "name": "phpunit/phpunit", - "version": "4.5.x-dev", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d6429b0995b24a2d9dfe5587ee3a7071c1161af4", - "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "~1.3,>=1.3.1", - "phpunit/php-code-coverage": "~2.0,>=2.0.11", - "phpunit/php-file-iterator": "~1.3.2", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0.2", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.1", - "sebastian/environment": "~1.2", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.5.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2015-03-29 09:24:05" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "~1.0,>=1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-04-02 05:36:41" - }, - { - "name": "psr/log", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-0": { - "Psr\\Log\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2012-12-21 11:40:51" - }, - { - "name": "satooshi/php-coveralls", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "2fbf803803d179ab1082807308a67bbd5a760c70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/2fbf803803d179ab1082807308a67bbd5a760c70", - "reference": "2fbf803803d179ab1082807308a67bbd5a760c70", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-simplexml": "*", - "guzzle/guzzle": ">=2.7", - "php": ">=5.3", - "psr/log": "1.0.0", - "symfony/config": ">=2.0", - "symfony/console": ">=2.0", - "symfony/stopwatch": ">=2.2", - "symfony/yaml": ">=2.0" - }, - "require-dev": { - "apigen/apigen": "2.8.*@stable", - "pdepend/pdepend": "dev-master as 2.0.0", - "phpmd/phpmd": "dev-master", - "phpunit/php-invoker": ">=1.1.0,<1.2.0", - "phpunit/phpunit": "3.7.*@stable", - "sebastian/finder-facade": "dev-master", - "sebastian/phpcpd": "1.4.*@stable", - "squizlabs/php_codesniffer": "1.4.*@stable", - "theseer/fdomdocument": "dev-master" - }, - "suggest": { - "symfony/http-kernel": "Allows Symfony integration" - }, - "bin": [ - "composer/bin/coveralls" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.7-dev" - } - }, - "autoload": { - "psr-0": { - "Satooshi\\Component": "src/", - "Satooshi\\Bundle": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kitamura Satoshi", - "email": "with.no.parachute@gmail.com", - "homepage": "https://www.facebook.com/satooshi.jp" - } - ], - "description": "PHP client library for Coveralls API", - "homepage": "https://github.com/satooshi/php-coveralls", - "keywords": [ - "ci", - "coverage", - "github", - "test" - ], - "time": "2014-11-11 15:35:34" - }, - { - "name": "sebastian/comparator", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2015-01-29 16:28:08" - }, - { - "name": "sebastian/diff", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "http://www.github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2015-02-22 15:13:53" - }, - { - "name": "sebastian/environment", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2015-01-01 10:01:08" - }, - { - "name": "sebastian/exporter", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "84839970d05254c73cde183a721c7af13aede943" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", - "reference": "84839970d05254c73cde183a721c7af13aede943", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2015-01-27 07:23:06" - }, - { - "name": "sebastian/global-state", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "007c441df427cf0e175372fcbb9d196bce7eb743" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/007c441df427cf0e175372fcbb9d196bce7eb743", - "reference": "007c441df427cf0e175372fcbb9d196bce7eb743", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-01-20 04:09:31" - }, - { - "name": "sebastian/recursion-context", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-01-24 09:48:32" - }, - { - "name": "sebastian/version", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-02-24 06:35:25" - }, - { - "name": "symfony/config", - "version": "dev-master", - "target-dir": "Symfony/Component/Config", - "source": { - "type": "git", - "url": "https://github.com/symfony/Config.git", - "reference": "631c3190d7fc8fe17094057867928c24bf6b9683" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/631c3190d7fc8fe17094057867928c24bf6b9683", - "reference": "631c3190d7fc8fe17094057867928c24bf6b9683", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "symfony/filesystem": "~2.7|~3.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Config\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Config Component", - "homepage": "http://symfony.com", - "time": "2015-04-08 05:30:14" - }, - { - "name": "symfony/console", - "version": "dev-master", - "target-dir": "Symfony/Component/Console", - "source": { - "type": "git", - "url": "https://github.com/symfony/Console.git", - "reference": "db3fa7b6c97abc09fa4e2b5be3f0e700469e589f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/db3fa7b6c97abc09fa4e2b5be3f0e700469e589f", - "reference": "db3fa7b6c97abc09fa4e2b5be3f0e700469e589f", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.7|~3.0", - "symfony/phpunit-bridge": "~2.7|~3.0", - "symfony/process": "~2.7|~3.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Console\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Console Component", - "homepage": "http://symfony.com", - "time": "2015-04-08 05:30:14" - }, - { - "name": "symfony/dependency-injection", - "version": "dev-master", - "target-dir": "Symfony/Component/DependencyInjection", - "source": { - "type": "git", - "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "4d12bccee943457b8999dcf83c31f62971173c20" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/4d12bccee943457b8999dcf83c31f62971173c20", - "reference": "4d12bccee943457b8999dcf83c31f62971173c20", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "symfony/config": "~2.7|~3.0", - "symfony/expression-language": "~2.7|~3.0", - "symfony/phpunit-bridge": "~2.7|~3.0", - "symfony/yaml": "~2.7|~3.0" - }, - "suggest": { - "symfony/config": "", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\DependencyInjection\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony DependencyInjection Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:59:03" - }, - { - "name": "symfony/event-dispatcher", - "version": "2.7.x-dev", - "target-dir": "Symfony/Component/EventDispatcher", - "source": { - "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "186349c2966529804e38685f671e64746dde220b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/186349c2966529804e38685f671e64746dde220b", - "reference": "186349c2966529804e38685f671e64746dde220b", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5|~3.0.0", - "symfony/dependency-injection": "~2.6|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/phpunit-bridge": "~2.7|~3.0.0", - "symfony/stopwatch": "~2.3|~3.0.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "http://symfony.com", - "time": "2015-03-13 17:50:01" - }, - { - "name": "symfony/filesystem", - "version": "dev-master", - "target-dir": "Symfony/Component/Filesystem", - "source": { - "type": "git", - "url": "https://github.com/symfony/Filesystem.git", - "reference": "afb9d158555bee3441dc5c1e68d9c35d332543eb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/afb9d158555bee3441dc5c1e68d9c35d332543eb", - "reference": "afb9d158555bee3441dc5c1e68d9c35d332543eb", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Filesystem\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "http://symfony.com", - "time": "2015-03-24 17:09:17" - }, - { - "name": "symfony/stopwatch", - "version": "dev-master", - "target-dir": "Symfony/Component/Stopwatch", - "source": { - "type": "git", - "url": "https://github.com/symfony/Stopwatch.git", - "reference": "bae98f9404e96f48e5e89f2fd3bb3f2dce52e431" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/bae98f9404e96f48e5e89f2fd3bb3f2dce52e431", - "reference": "bae98f9404e96f48e5e89f2fd3bb3f2dce52e431", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Stopwatch\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Stopwatch Component", - "homepage": "http://symfony.com", - "time": "2015-03-24 17:09:17" - }, - { - "name": "symfony/yaml", - "version": "2.7.x-dev", - "target-dir": "Symfony/Component/Yaml", - "source": { - "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "3882af2f22672e347030b561cc6c5abc2b335566" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/3882af2f22672e347030b561cc6c5abc2b335566", - "reference": "3882af2f22672e347030b561cc6c5abc2b335566", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Yaml\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Yaml Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:55:07" - } - ], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=5.3.0" - }, - "platform-dev": [] -} diff --git a/grumphp.yml b/grumphp.yml new file mode 100644 index 0000000..cb58221 --- /dev/null +++ b/grumphp.yml @@ -0,0 +1,21 @@ +parameters: + ascii: + failed: ~ + succeeded: ~ + git_dir: . + bin_dir: bin + tasks: + phpcs: + standard: "PSR2" + show_warnings: false + blacklist: + keywords: + - "die(" + - "var_dump(" + - "print_r(" + - "print(" + - "dump(" + - "debug_backtrace(" + - "file_put_contents(" + - "exit;" + - "echo" diff --git a/lib/PHPExif/Adapter/AdapterAbstract.php b/lib/PHPExif/Adapter/AdapterAbstract.php deleted file mode 100644 index d7d06c3..0000000 --- a/lib/PHPExif/Adapter/AdapterAbstract.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Reader - */ - -namespace PHPExif\Adapter; - -use PHPExif\Mapper\MapperInterface; -use PHPExif\Hydrator\HydratorInterface; - -/** - * PHP Exif Reader Adapter Abstract - * - * Implements common functionality for the reader adapters - * - * @category PHPExif - * @package Reader - */ -abstract class AdapterAbstract implements AdapterInterface -{ - /** - * @var string - */ - protected $hydratorClass = '\\PHPExif\\Hydrator\\Mutator'; - - /** - * @var \PHPExif\Mapper\MapperInterface - */ - protected $mapper; - - /** - * @var \PHPExif\Hydrator\HydratorInterface - */ - protected $hydrator; - - /** - * @var string - */ - protected $mapperClass = ''; - - /** - * Class constructor - * - * @param array $options Optional array of data to initialize the object with - */ - public function __construct(array $options = array()) - { - if (!empty($options)) { - $this->setOptions($options); - } - } - - /** - * Mutator for the data mapper - * - * @param \PHPExif\Mapper\MapperInterface $mapper - * @return \PHPExif\Adapter\AdapterInterface - */ - public function setMapper(MapperInterface $mapper) - { - $this->mapper = $mapper; - - return $this; - } - - /** - * Accessor for the data mapper - * - * @return \PHPExif\Mapper\MapperInterface - */ - public function getMapper() - { - if (null === $this->mapper) { - // lazy load one - $mapper = new $this->mapperClass; - - $this->setMapper($mapper); - } - - return $this->mapper; - } - - /** - * Mutator for the hydrator - * - * @param \PHPExif\Hydrator\HydratorInterface $hydrator - * @return \PHPExif\Adapter\AdapterInterface - */ - public function setHydrator(HydratorInterface $hydrator) - { - $this->hydrator = $hydrator; - - return $this; - } - - /** - * Accessor for the data hydrator - * - * @return \PHPExif\Hydrator\HydratorInterface - */ - public function getHydrator() - { - if (null === $this->hydrator) { - // lazy load one - $hydrator = new $this->hydratorClass; - - $this->setHydrator($hydrator); - } - - return $this->hydrator; - } - - /** - * Set array of options in the current object - * - * @param array $options - * @return \PHPExif\Reader\AdapterAbstract - */ - public function setOptions(array $options) - { - $hydrator = $this->getHydrator(); - $hydrator->hydrate($this, $options); - - return $this; - } -} diff --git a/lib/PHPExif/Adapter/AdapterInterface.php b/lib/PHPExif/Adapter/AdapterInterface.php deleted file mode 100644 index 780e77d..0000000 --- a/lib/PHPExif/Adapter/AdapterInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Reader - * @codeCoverageIgnore - */ - -namespace PHPExif\Adapter; - -/** - * PHP Exif Reader Adapter - * - * Defines the interface for reader adapters - * - * @category PHPExif - * @package Reader - */ -interface AdapterInterface -{ - /** - * Reads & parses the EXIF data from given file - * - * @param string $file - * @return \PHPExif\Exif Instance of Exif object with data - * @throws \RuntimeException If the EXIF data could not be read - */ - public function getExifFromFile($file); -} diff --git a/lib/PHPExif/Adapter/Exiftool.php b/lib/PHPExif/Adapter/Exiftool.php deleted file mode 100644 index 2319dee..0000000 --- a/lib/PHPExif/Adapter/Exiftool.php +++ /dev/null @@ -1,161 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Reader - */ - -namespace PHPExif\Adapter; - -use PHPExif\Exif; -use InvalidArgumentException; -use RuntimeException; - -/** - * PHP Exif Exiftool Reader Adapter - * - * Uses native PHP functionality to read data from a file - * - * @category PHPExif - * @package Reader - */ -class Exiftool extends AdapterAbstract -{ - const TOOL_NAME = 'exiftool'; - - /** - * Path to the exiftool binary - * - * @var string - */ - protected $toolPath; - - /** - * @var boolean - */ - protected $numeric = true; - - /** - * @var string - */ - protected $mapperClass = '\\PHPExif\\Mapper\\Exiftool'; - - /** - * Setter for the exiftool binary path - * - * @param string $path The path to the exiftool binary - * @return \PHPExif\Adapter\Exiftool Current instance - * @throws \InvalidArgumentException When path is invalid - */ - public function setToolPath($path) - { - if (!file_exists($path)) { - throw new InvalidArgumentException( - sprintf( - 'Given path (%1$s) to the exiftool binary is invalid', - $path - ) - ); - } - - $this->toolPath = $path; - - return $this; - } - - /** - * @param boolean $numeric - */ - public function setNumeric($numeric) - { - $this->numeric = $numeric; - } - - /** - * Getter for the exiftool binary path - * Lazy loads the "default" path - * - * @return string - */ - public function getToolPath() - { - if (empty($this->toolPath)) { - $path = exec('which ' . self::TOOL_NAME); - $this->setToolPath($path); - } - - return $this->toolPath; - } - - /** - * Reads & parses the EXIF data from given file - * - * @param string $file - * @return \PHPExif\Exif Instance of Exif object with data - * @throws \RuntimeException If the EXIF data could not be read - */ - public function getExifFromFile($file) - { - $result = $this->getCliOutput( - sprintf( - '%1$s%3$s -j -a -G1 -c %4$s %2$s', - $this->getToolPath(), - escapeshellarg($file), - $this->numeric ? ' -n' : '', - escapeshellarg('%d deg %d\' %.4f"') - ) - ); - - $data = json_decode(utf8_encode($result), true); - - // map the data: - $mapper = $this->getMapper(); - $mapper->setNumeric($this->numeric); - $mappedData = $mapper->mapRawData(reset($data)); - - // hydrate a new Exif object - $exif = new Exif(); - $hydrator = $this->getHydrator(); - $hydrator->hydrate($exif, $mappedData); - $exif->setRawData(reset($data)); - - return $exif; - } - - /** - * Returns the output from given cli command - * - * @param string $command - * @return mixed - * @throws RuntimeException If the command can't be executed - */ - protected function getCliOutput($command) - { - $descriptorspec = array( - 0 => array('pipe', 'r'), - 1 => array('pipe', 'w'), - 2 => array('pipe', 'a') - ); - - $process = proc_open($command, $descriptorspec, $pipes); - - if (!is_resource($process)) { - throw new RuntimeException( - 'Could not open a resource to the exiftool binary' - ); - } - - $result = stream_get_contents($pipes[1]); - fclose($pipes[0]); - fclose($pipes[1]); - fclose($pipes[2]); - - proc_close($process); - - return $result; - } -} diff --git a/lib/PHPExif/Adapter/Native.php b/lib/PHPExif/Adapter/Native.php deleted file mode 100644 index a5c99ec..0000000 --- a/lib/PHPExif/Adapter/Native.php +++ /dev/null @@ -1,239 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Reader - */ - -namespace PHPExif\Adapter; - -use PHPExif\Exif; -use DateTime; - -/** - * PHP Exif Native Reader Adapter - * - * Uses native PHP functionality to read data from a file - * - * @category PHPExif - * @package Reader - */ -class Native extends AdapterAbstract -{ - const INCLUDE_THUMBNAIL = true; - const NO_THUMBNAIL = false; - - const SECTIONS_AS_ARRAYS = true; - const SECTIONS_FLAT = false; - - const SECTION_FILE = 'FILE'; - const SECTION_COMPUTED = 'COMPUTED'; - const SECTION_IFD0 = 'IFD0'; - const SECTION_THUMBNAIL = 'THUMBNAIL'; - const SECTION_COMMENT = 'COMMENT'; - const SECTION_EXIF = 'EXIF'; - const SECTION_ALL = 'ANY_TAG'; - const SECTION_IPTC = 'IPTC'; - - /** - * List of EXIF sections - * - * @var array - */ - protected $requiredSections = array(); - - /** - * Include the thumbnail in the EXIF data? - * - * @var boolean - */ - protected $includeThumbnail = self::NO_THUMBNAIL; - - /** - * Parse the sections as arrays? - * - * @var boolean - */ - protected $sectionsAsArrays = self::SECTIONS_FLAT; - - /** - * @var string - */ - protected $mapperClass = '\\PHPExif\\Mapper\\Native'; - - /** - * Contains the mapping of names to IPTC field numbers - * - * @var array - */ - protected $iptcMapping = array( - 'title' => '2#005', - 'keywords' => '2#025', - 'copyright' => '2#116', - 'caption' => '2#120', - 'headline' => '2#105', - 'credit' => '2#110', - 'source' => '2#115', - 'jobtitle' => '2#085' - ); - - - /** - * Getter for the EXIF sections - * - * @return array - */ - public function getRequiredSections() - { - return $this->requiredSections; - } - - /** - * Setter for the EXIF sections - * - * @param array $sections List of EXIF sections - * @return \PHPExif\Reader Current instance for chaining - */ - public function setRequiredSections(array $sections) - { - $this->requiredSections = $sections; - - return $this; - } - - /** - * Adds an EXIF section to the list - * - * @param string $section - * @return \PHPExif\Reader Current instance for chaining - */ - public function addRequiredSection($section) - { - if (!in_array($section, $this->requiredSections)) { - array_push($this->requiredSections, $section); - } - - return $this; - } - - /** - * Define if the thumbnail should be included into the EXIF data or not - * - * @param boolean $value - * @return \PHPExif\Reader Current instance for chaining - */ - public function setIncludeThumbnail($value) - { - $this->includeThumbnail = $value; - - return $this; - } - - /** - * Returns if the thumbnail should be included into the EXIF data or not - * - * @return boolean - */ - public function getIncludeThumbnail() - { - return $this->includeThumbnail; - } - - /** - * Define if the sections should be parsed as arrays - * - * @param boolean $value - * @return \PHPExif\Reader Current instance for chaining - */ - public function setSectionsAsArrays($value) - { - $this->sectionsAsArrays = (bool) $value; - - return $this; - } - - /** - * Returns if the sections should be parsed as arrays - * - * @return boolean - */ - public function getSectionsAsArrays() - { - return $this->sectionsAsArrays; - } - - /** - * Reads & parses the EXIF data from given file - * - * @param string $file - * @return \PHPExif\Exif Instance of Exif object with data - * @throws \RuntimeException If the EXIF data could not be read - */ - public function getExifFromFile($file) - { - $sections = $this->getRequiredSections(); - $sections = implode(',', $sections); - $sections = (empty($sections)) ? null : $sections; - - $data = @exif_read_data( - $file, - $sections, - $this->getSectionsAsArrays(), - $this->getIncludeThumbnail() - ); - - if (false === $data) { - throw new \RuntimeException( - sprintf('Could not read EXIF data from file %1$s', $file) - ); - } - - $xmpData = $this->getIptcData($file); - $data = array_merge($data, array(self::SECTION_IPTC => $xmpData)); - - // map the data: - $mapper = $this->getMapper(); - $mappedData = $mapper->mapRawData($data); - - // hydrate a new Exif object - $exif = new Exif(); - $hydrator = $this->getHydrator(); - $hydrator->hydrate($exif, $mappedData); - $exif->setRawData($data); - - return $exif; - } - - /** - * Returns an array of IPTC data - * - * @param string $file The file to read the IPTC data from - * @return array - */ - public function getIptcData($file) - { - getimagesize($file, $info); - $arrData = array(); - if (isset($info['APP13'])) { - $iptc = iptcparse($info['APP13']); - - foreach ($this->iptcMapping as $name => $field) { - if (!isset($iptc[$field])) { - continue; - } - - if (count($iptc[$field]) === 1) { - $arrData[$name] = reset($iptc[$field]); - } else { - $arrData[$name] = $iptc[$field]; - } - } - } - - return $arrData; - } -} diff --git a/lib/PHPExif/Exif.php b/lib/PHPExif/Exif.php deleted file mode 100755 index e6614e4..0000000 --- a/lib/PHPExif/Exif.php +++ /dev/null @@ -1,843 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Exif - */ - -namespace PHPExif; - -/** - * PHP Exif Reader - * - * Responsible for all the read operations on a file's EXIF metadata - * - * @category PHPExif - * @package Exif - * @ - */ -class Exif -{ - const APERTURE = 'aperture'; - const AUTHOR = 'author'; - const CAMERA = 'camera'; - const CAPTION = 'caption'; - const COLORSPACE = 'ColorSpace'; - const COPYRIGHT = 'copyright'; - const CREATION_DATE = 'creationdate'; - const CREDIT = 'credit'; - const EXPOSURE = 'exposure'; - const FILESIZE = 'FileSize'; - const FOCAL_LENGTH = 'focalLength'; - const FOCAL_DISTANCE = 'focalDistance'; - const HEADLINE = 'headline'; - const HEIGHT = 'height'; - const HORIZONTAL_RESOLUTION = 'horizontalResolution'; - const ISO = 'iso'; - const JOB_TITLE = 'jobTitle'; - const KEYWORDS = 'keywords'; - const MIMETYPE = 'MimeType'; - const ORIENTATION = 'Orientation'; - const SOFTWARE = 'software'; - const SOURCE = 'source'; - const TITLE = 'title'; - const VERTICAL_RESOLUTION = 'verticalResolution'; - const WIDTH = 'width'; - const GPS = 'gps'; - - /** - * The mapped EXIF data - * - * @var array - */ - protected $data = array(); - - /** - * The raw EXIF data - * - * @var array - */ - protected $rawData = array(); - - /** - * Class constructor - * - * @param array $data - */ - public function __construct(array $data = array()) - { - $this->setData($data); - } - - /** - * Sets the raw EXIF data - * - * @param array $data The data to set - * @return \PHPExif\Exif Current instance for chaining - */ - public function setRawData(array $data) - { - $this->rawData = $data; - - return $this; - } - - /** - * Returns all EXIF data in the raw original format - * - * @return array - */ - public function getRawData() - { - return $this->rawData; - } - - /** - * Sets the mapped EXIF data - * - * @param array $data The data to set - * @return \PHPExif\Exif Current instance for chaining - */ - public function setData(array $data) - { - $this->data = $data; - - return $this; - } - - /** - * Returns the mapped EXIF data - * - * @return array - */ - public function getData() - { - return $this->data; - } - - /** - * Returns the Aperture F-number - * - * @return string|boolean - */ - public function getAperture() - { - if (!isset($this->data[self::APERTURE])) { - return false; - } - - return $this->data[self::APERTURE]; - } - - /** - * Sets the Aperture F-number - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setAperture($value) - { - $this->data[self::APERTURE] = $value; - - return $this; - } - - /** - * Returns the Author - * - * @return string|boolean - */ - public function getAuthor() - { - if (!isset($this->data[self::AUTHOR])) { - return false; - } - - return $this->data[self::AUTHOR]; - } - - /** - * Sets the Author - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setAuthor($value) - { - $this->data[self::AUTHOR] = $value; - - return $this; - } - - /** - * Returns the Headline - * - * @return string|boolean - */ - public function getHeadline() - { - if (!isset($this->data[self::HEADLINE])) { - return false; - } - - return $this->data[self::HEADLINE]; - } - - /** - * Sets the Headline - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setHeadline($value) - { - $this->data[self::HEADLINE] = $value; - - return $this; - } - - /** - * Returns the Credit - * - * @return string|boolean - */ - public function getCredit() - { - if (!isset($this->data[self::CREDIT])) { - return false; - } - - return $this->data[self::CREDIT]; - } - - /** - * Sets the Credit - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setCredit($value) - { - $this->data[self::CREDIT] = $value; - - return $this; - } - - /** - * Returns the source - * - * @return string|boolean - */ - public function getSource() - { - if (!isset($this->data[self::SOURCE])) { - return false; - } - - return $this->data[self::SOURCE]; - } - - /** - * Sets the Source - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setSource($value) - { - $this->data[self::SOURCE] = $value; - - return $this; - } - - /** - * Returns the Jobtitle - * - * @return string|boolean - */ - public function getJobtitle() - { - if (!isset($this->data[self::JOB_TITLE])) { - return false; - } - - return $this->data[self::JOB_TITLE]; - } - - /** - * Sets the Jobtitle - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setJobtitle($value) - { - $this->data[self::JOB_TITLE] = $value; - - return $this; - } - - /** - * Returns the ISO speed - * - * @return int|boolean - */ - public function getIso() - { - if (!isset($this->data[self::ISO])) { - return false; - } - - return $this->data[self::ISO]; - } - - /** - * Sets the ISO - * - * @param int $value - * @return \PHPExif\Exif - */ - public function setIso($value) - { - $this->data[self::ISO] = $value; - - return $this; - } - - /** - * Returns the Exposure - * - * @return string|boolean - */ - public function getExposure() - { - if (!isset($this->data[self::EXPOSURE])) { - return false; - } - - return $this->data[self::EXPOSURE]; - } - - /** - * Sets the Exposure - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setExposure($value) - { - $this->data[self::EXPOSURE] = $value; - - return $this; - } - - /** - * Returns the Exposure - * - * @return float|boolean - */ - public function getExposureMilliseconds() - { - if (!isset($this->data[self::EXPOSURE])) { - return false; - } - - if (is_numeric($this->data[self::EXPOSURE])) { - return $this->data[self::EXPOSURE] + 0; - } - - $exposureParts = explode('/', $this->data[self::EXPOSURE]); - - return (int) reset($exposureParts) / (int) end($exposureParts); - } - - /** - * Returns the focus distance, if it exists - * - * @return string|boolean - */ - public function getFocusDistance() - { - if (!isset($this->data[self::FOCAL_DISTANCE])) { - return false; - } - - return $this->data[self::FOCAL_DISTANCE]; - } - - /** - * Sets the focus distance - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setFocusDistance($value) - { - $this->data[self::FOCAL_DISTANCE] = $value; - - return $this; - } - - /** - * Returns the width in pixels, if it exists - * - * @return int|boolean - */ - public function getWidth() - { - if (!isset($this->data[self::WIDTH])) { - return false; - } - - return $this->data[self::WIDTH]; - } - - /** - * Sets the width - * - * @param int $value - * @return \PHPExif\Exif - */ - public function setWidth($value) - { - $this->data[self::WIDTH] = $value; - - return $this; - } - - /** - * Returns the height in pixels, if it exists - * - * @return int|boolean - */ - public function getHeight() - { - if (!isset($this->data[self::HEIGHT])) { - return false; - } - - return $this->data[self::HEIGHT]; - } - - /** - * Sets the height - * - * @param int $value - * @return \PHPExif\Exif - */ - public function setHeight($value) - { - $this->data[self::HEIGHT] = $value; - - return $this; - } - - /** - * Returns the title, if it exists - * - * @return string|boolean - */ - public function getTitle() - { - if (!isset($this->data[self::TITLE])) { - return false; - } - - return $this->data[self::TITLE]; - } - - /** - * Sets the title - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setTitle($value) - { - $this->data[self::TITLE] = $value; - - return $this; - } - - /** - * Returns the caption, if it exists - * - * @return string|boolean - */ - public function getCaption() - { - if (!isset($this->data[self::CAPTION])) { - return false; - } - - return $this->data[self::CAPTION]; - } - - /** - * Sets the caption - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setCaption($value) - { - $this->data[self::CAPTION] = $value; - - return $this; - } - - /** - * Returns the copyright, if it exists - * - * @return string|boolean - */ - public function getCopyright() - { - if (!isset($this->data[self::COPYRIGHT])) { - return false; - } - - return $this->data[self::COPYRIGHT]; - } - - /** - * Sets the copyright - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setCopyright($value) - { - $this->data[self::COPYRIGHT] = $value; - - return $this; - } - - /** - * Returns the keywords, if they exists - * - * @return array|boolean - */ - public function getKeywords() - { - if (!isset($this->data[self::KEYWORDS])) { - return false; - } - - return $this->data[self::KEYWORDS]; - } - - /** - * Sets the keywords - * - * @param array $value - * @return \PHPExif\Exif - */ - public function setKeywords($value) - { - $this->data[self::KEYWORDS] = $value; - - return $this; - } - - /** - * Returns the camera, if it exists - * - * @return string|boolean - */ - public function getCamera() - { - if (!isset($this->data[self::CAMERA])) { - return false; - } - - return $this->data[self::CAMERA]; - } - - /** - * Sets the camera - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setCamera($value) - { - $this->data[self::CAMERA] = $value; - - return $this; - } - - /** - * Returns the horizontal resolution in DPI, if it exists - * - * @return int|boolean - */ - public function getHorizontalResolution() - { - if (!isset($this->data[self::HORIZONTAL_RESOLUTION])) { - return false; - } - - return $this->data[self::HORIZONTAL_RESOLUTION]; - } - - /** - * Sets the horizontal resolution in DPI - * - * @param int $value - * @return \PHPExif\Exif - */ - public function setHorizontalResolution($value) - { - $this->data[self::HORIZONTAL_RESOLUTION] = $value; - - return $this; - } - - /** - * Returns the vertical resolution in DPI, if it exists - * - * @return int|boolean - */ - public function getVerticalResolution() - { - if (!isset($this->data[self::VERTICAL_RESOLUTION])) { - return false; - } - - return $this->data[self::VERTICAL_RESOLUTION]; - } - - /** - * Sets the vertical resolution in DPI - * - * @param int $value - * @return \PHPExif\Exif - */ - public function setVerticalResolution($value) - { - $this->data[self::VERTICAL_RESOLUTION] = $value; - - return $this; - } - - /** - * Returns the software, if it exists - * - * @return string|boolean - */ - public function getSoftware() - { - if (!isset($this->data[self::SOFTWARE])) { - return false; - } - - return $this->data[self::SOFTWARE]; - } - - /** - * Sets the software - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setSoftware($value) - { - $this->data[self::SOFTWARE] = trim($value); - - return $this; - } - - /** - * Returns the focal length in mm, if it exists - * - * @return float|boolean - */ - public function getFocalLength() - { - if (!isset($this->data[self::FOCAL_LENGTH])) { - return false; - } - - return $this->data[self::FOCAL_LENGTH]; - } - - /** - * Sets the focal length in mm - * - * @param float $value - * @return \PHPExif\Exif - */ - public function setFocalLength($value) - { - $this->data[self::FOCAL_LENGTH] = $value; - - return $this; - } - - /** - * Returns the creation datetime, if it exists - * - * @return \DateTime|boolean - */ - public function getCreationDate() - { - if (!isset($this->data[self::CREATION_DATE])) { - return false; - } - - return $this->data[self::CREATION_DATE]; - } - - /** - * Sets the creation datetime - * - * @param \DateTime $value - * @return \PHPExif\Exif - */ - public function setCreationDate(\DateTime $value) - { - $this->data[self::CREATION_DATE] = $value; - - return $this; - } - - /** - * Returns the colorspace, if it exists - * - * @return string|boolean - */ - public function getColorSpace() - { - if (!isset($this->data[self::COLORSPACE])) { - return false; - } - - return $this->data[self::COLORSPACE]; - } - - /** - * Sets the colorspace - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setColorSpace($value) - { - $this->data[self::COLORSPACE] = $value; - - return $this; - } - - /** - * Returns the mimetype, if it exists - * - * @return string|boolean - */ - public function getMimeType() - { - if (!isset($this->data[self::MIMETYPE])) { - return false; - } - - return $this->data[self::MIMETYPE]; - } - - /** - * Sets the mimetype - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setMimeType($value) - { - $this->data[self::MIMETYPE] = $value; - - return $this; - } - - /** - * Returns the filesize, if it exists - * - * @return int|boolean - */ - public function getFileSize() - { - if (!isset($this->data[self::FILESIZE])) { - return false; - } - - return $this->data[self::FILESIZE]; - } - - /** - * Sets the filesize - * - * @param int $value - * @return \PHPExif\Exif - */ - public function setFileSize($value) - { - $this->data[self::FILESIZE] = $value; - - return $this; - } - - /** - * Returns the orientation, if it exists - * - * @return int|boolean - */ - public function getOrientation() - { - if (!isset($this->data[self::ORIENTATION])) { - return false; - } - - return $this->data[self::ORIENTATION]; - } - - /** - * Sets the orientation - * - * @param int $value - * @return \PHPExif\Exif - */ - public function setOrientation($value) - { - $this->data[self::ORIENTATION] = $value; - - return $this; - } - - /** - * Returns GPS coordinates, if it exists - * - * @return array|boolean - */ - public function getGPS() - { - if (!isset($this->data[self::GPS])) { - return false; - } - - return $this->data[self::GPS]; - } - - /** - * Sets the GPS coordinates - * - * @param string $value - * @return \PHPExif\Exif - */ - public function setGPS($value) - { - $this->data[self::GPS] = $value; - - return $this; - } -} diff --git a/lib/PHPExif/Hydrator/HydratorInterface.php b/lib/PHPExif/Hydrator/HydratorInterface.php deleted file mode 100644 index d884327..0000000 --- a/lib/PHPExif/Hydrator/HydratorInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Hydrator - * @codeCoverageIgnore - */ - -namespace PHPExif\Hydrator; - -/** - * PHP Exif Hydrator - * - * Defines the interface for a hydrator - * - * @category PHPExif - * @package Hydrator - */ -interface HydratorInterface -{ - /** - * Hydrates given array of data into the given Exif object - * - * @param object $object - * @param array $data - * @return void - */ - public function hydrate($object, array $data); -} diff --git a/lib/PHPExif/Hydrator/Mutator.php b/lib/PHPExif/Hydrator/Mutator.php deleted file mode 100644 index 9c8a0d6..0000000 --- a/lib/PHPExif/Hydrator/Mutator.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Hydrator - */ - -namespace PHPExif\Hydrator; - -/** - * PHP Exif Mutator Hydrator - * - * Hydrates an object by setting data with - * the class mutator methods - * - * @category PHPExif - * @package Hydrator - */ -class Mutator implements HydratorInterface -{ - /** - * Hydrates given array of data into the given Exif object - * - * @param object $object - * @param array $data - * @return void - */ - public function hydrate($object, array $data) - { - foreach ($data as $property => $value) { - - $mutator = $this->determineMutator($property); - - if (method_exists($object, $mutator)) { - $object->$mutator($value); - } - } - } - - /** - * Determines the name of the mutator method for given property name - * - * @param string $property The property to determine the mutator for - * @return string The name of the mutator method - */ - protected function determineMutator($property) - { - $method = 'set' . ucfirst($property); - return $method; - } -} diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php deleted file mode 100644 index 89e205e..0000000 --- a/lib/PHPExif/Mapper/Exiftool.php +++ /dev/null @@ -1,210 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Mapper - */ - -namespace PHPExif\Mapper; - -use PHPExif\Exif; -use DateTime; - -/** - * PHP Exif Exiftool Mapper - * - * Maps Exiftool raw data to valid data for the \PHPExif\Exif class - * - * @category PHPExif - * @package Mapper - */ -class Exiftool implements MapperInterface -{ - const APERTURE = 'Composite:Aperture'; - const APPROXIMATEFOCUSDISTANCE = 'XMP-aux:ApproximateFocusDistance'; - const ARTIST = 'IFD0:Artist'; - const CAPTION = 'XMP-acdsee'; - const CAPTIONABSTRACT = 'IPTC:Caption-Abstract'; - const COLORSPACE = 'ExifIFD:ColorSpace'; - const COPYRIGHT = 'IFD0:Copyright'; - const DATETIMEORIGINAL = 'ExifIFD:DateTimeOriginal'; - const CREDIT = 'IPTC:Credit'; - const EXPOSURETIME = 'ExifIFD:ExposureTime'; - const FILESIZE = 'System:FileSize'; - const FOCALLENGTH = 'ExifIFD:FocalLength'; - const HEADLINE = 'IPTC:Headline'; - const IMAGEHEIGHT = 'File:ImageHeight'; - const IMAGEWIDTH = 'File:ImageWidth'; - const ISO = 'ExifIFD:ISO'; - const JOBTITLE = 'IPTC:By-lineTitle'; - const KEYWORDS = 'IPTC:Keywords'; - const MIMETYPE = 'File:MIMEType'; - const MODEL = 'IFD0:Model'; - const ORIENTATION = 'IFD0:Orientation'; - const SOFTWARE = 'IFD0:Software'; - const SOURCE = 'IPTC:Source'; - const TITLE = 'IPTC:ObjectName'; - const XRESOLUTION = 'IFD0:XResolution'; - const YRESOLUTION = 'IFD0:YResolution'; - const GPSLATITUDE = 'GPS:GPSLatitude'; - const GPSLONGITUDE = 'GPS:GPSLongitude'; - - /** - * Maps the ExifTool fields to the fields of - * the \PHPExif\Exif class - * - * @var array - */ - protected $map = array( - self::APERTURE => Exif::APERTURE, - self::ARTIST => Exif::AUTHOR, - self::MODEL => Exif::CAMERA, - self::CAPTION => Exif::CAPTION, - self::COLORSPACE => Exif::COLORSPACE, - self::COPYRIGHT => Exif::COPYRIGHT, - self::DATETIMEORIGINAL => Exif::CREATION_DATE, - self::CREDIT => Exif::CREDIT, - self::EXPOSURETIME => Exif::EXPOSURE, - self::FILESIZE => Exif::FILESIZE, - self::FOCALLENGTH => Exif::FOCAL_LENGTH, - self::APPROXIMATEFOCUSDISTANCE => Exif::FOCAL_DISTANCE, - self::HEADLINE => Exif::HEADLINE, - self::IMAGEHEIGHT => Exif::HEIGHT, - self::XRESOLUTION => Exif::HORIZONTAL_RESOLUTION, - self::ISO => Exif::ISO, - self::JOBTITLE => Exif::JOB_TITLE, - self::KEYWORDS => Exif::KEYWORDS, - self::MIMETYPE => Exif::MIMETYPE, - self::ORIENTATION => Exif::ORIENTATION, - self::SOFTWARE => Exif::SOFTWARE, - self::SOURCE => Exif::SOURCE, - self::TITLE => Exif::TITLE, - self::YRESOLUTION => Exif::VERTICAL_RESOLUTION, - self::IMAGEWIDTH => Exif::WIDTH, - self::CAPTIONABSTRACT => Exif::CAPTION, - self::GPSLATITUDE => Exif::GPS, - self::GPSLONGITUDE => Exif::GPS, - ); - - /** - * @var bool - */ - protected $numeric = true; - - /** - * Mutator method for the numeric property - * - * @param bool $numeric - * @return \PHPExif\Mapper\Exiftool - */ - public function setNumeric($numeric) - { - $this->numeric = (bool) $numeric; - - return $this; - } - - /** - * Maps the array of raw source data to the correct - * fields for the \PHPExif\Exif class - * - * @param array $data - * @return array - */ - public function mapRawData(array $data) - { - $mappedData = array(); - $gpsData = array(); - foreach ($data as $field => $value) { - if (!array_key_exists($field, $this->map)) { - // silently ignore unknown fields - continue; - } - - $key = $this->map[$field]; - - // manipulate the value if necessary - switch ($field) { - case self::APERTURE: - $value = sprintf('f/%01.1f', $value); - break; - case self::APPROXIMATEFOCUSDISTANCE: - $value = sprintf('%1$sm', $value); - break; - case self::DATETIMEORIGINAL: - try { - $value = new DateTime($value); - } catch (\Exception $exception) { - continue 2; - } - break; - case self::EXPOSURETIME: - // Based on the source code of Exiftool (PrintExposureTime subroutine): - // http://cpansearch.perl.org/src/EXIFTOOL/Image-ExifTool-9.90/lib/Image/ExifTool/Exif.pm - if ($value < 0.25001 && $value > 0) { - $value = sprintf('1/%d', intval(0.5 + 1 / $value)); - } else { - $value = sprintf('%.1f', $value); - $value = preg_replace('/.0$/', '', $value); - } - break; - case self::FOCALLENGTH: - if (!$this->numeric || strpos($value, ' ') !== false) { - $focalLengthParts = explode(' ', $value); - $value = reset($focalLengthParts); - } - break; - case self::GPSLATITUDE: - $gpsData['lat'] = $this->extractGPSCoordinates($value); - break; - case self::GPSLONGITUDE: - $gpsData['lon'] = $this->extractGPSCoordinates($value); - break; - } - - // set end result - $mappedData[$key] = $value; - } - - // add GPS coordinates, if available - if (count($gpsData) === 2 && $gpsData['lat'] !== false && $gpsData['lon'] !== false) { - $latitudeRef = empty($data['GPS:GPSLatitudeRef'][0]) ? 'N' : $data['GPS:GPSLatitudeRef'][0]; - $longitudeRef = empty($data['GPS:GPSLongitudeRef'][0]) ? 'E' : $data['GPS:GPSLongitudeRef'][0]; - - $gpsLocation = sprintf( - '%s,%s', - (strtoupper($latitudeRef) === 'S' ? -1 : 1) * $gpsData['lat'], - (strtoupper($longitudeRef) === 'W' ? -1 : 1) * $gpsData['lon'] - ); - - $mappedData[Exif::GPS] = $gpsLocation; - } else { - unset($mappedData[Exif::GPS]); - } - - return $mappedData; - } - - /** - * Extract GPS coordinates from formatted string - * - * @param string $coordinates - * @return array - */ - protected function extractGPSCoordinates($coordinates) - { - if ($this->numeric === true) { - return abs((float) $coordinates); - } else { - if (!preg_match('!^([0-9.]+) deg ([0-9.]+)\' ([0-9.]+)"!', $coordinates, $matches)) { - return false; - } - - return intval($matches[1]) + (intval($matches[2]) / 60) + (floatval($matches[3]) / 3600); - } - } -} diff --git a/lib/PHPExif/Mapper/Native.php b/lib/PHPExif/Mapper/Native.php deleted file mode 100644 index 0268cfd..0000000 --- a/lib/PHPExif/Mapper/Native.php +++ /dev/null @@ -1,254 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Mapper - */ - -namespace PHPExif\Mapper; - -use PHPExif\Exif; -use DateTime; -use Exception; - -/** - * PHP Exif Native Mapper - * - * Maps native raw data to valid data for the \PHPExif\Exif class - * - * @category PHPExif - * @package Mapper - */ -class Native implements MapperInterface -{ - const APERTUREFNUMBER = 'ApertureFNumber'; - const ARTIST = 'Artist'; - const CAPTION = 'caption'; - const COLORSPACE = 'ColorSpace'; - const COPYRIGHT = 'copyright'; - const DATETIMEORIGINAL = 'DateTimeOriginal'; - const CREDIT = 'credit'; - const EXPOSURETIME = 'ExposureTime'; - const FILESIZE = 'FileSize'; - const FOCALLENGTH = 'FocalLength'; - const FOCUSDISTANCE = 'FocusDistance'; - const HEADLINE = 'headline'; - const HEIGHT = 'Height'; - const ISOSPEEDRATINGS = 'ISOSpeedRatings'; - const JOBTITLE = 'jobtitle'; - const KEYWORDS = 'keywords'; - const MIMETYPE = 'MimeType'; - const MODEL = 'Model'; - const ORIENTATION = 'Orientation'; - const SOFTWARE = 'Software'; - const SOURCE = 'source'; - const TITLE = 'title'; - const WIDTH = 'Width'; - const XRESOLUTION = 'XResolution'; - const YRESOLUTION = 'YResolution'; - const GPSLATITUDE = 'GPSLatitude'; - const GPSLONGITUDE = 'GPSLongitude'; - - const SECTION_FILE = 'FILE'; - const SECTION_COMPUTED = 'COMPUTED'; - const SECTION_IFD0 = 'IFD0'; - const SECTION_THUMBNAIL = 'THUMBNAIL'; - const SECTION_COMMENT = 'COMMENT'; - const SECTION_EXIF = 'EXIF'; - const SECTION_ALL = 'ANY_TAG'; - const SECTION_IPTC = 'IPTC'; - - /** - * A list of section names - * - * @var array - */ - protected $sections = array( - self::SECTION_FILE, - self::SECTION_COMPUTED, - self::SECTION_IFD0, - self::SECTION_THUMBNAIL, - self::SECTION_COMMENT, - self::SECTION_EXIF, - self::SECTION_ALL, - self::SECTION_IPTC, - ); - - /** - * Maps the ExifTool fields to the fields of - * the \PHPExif\Exif class - * - * @var array - */ - protected $map = array( - self::APERTUREFNUMBER => Exif::APERTURE, - self::FOCUSDISTANCE => Exif::FOCAL_DISTANCE, - self::HEIGHT => Exif::HEIGHT, - self::WIDTH => Exif::WIDTH, - self::CAPTION => Exif::CAPTION, - self::COPYRIGHT => Exif::COPYRIGHT, - self::CREDIT => Exif::CREDIT, - self::HEADLINE => Exif::HEADLINE, - self::JOBTITLE => Exif::JOB_TITLE, - self::KEYWORDS => Exif::KEYWORDS, - self::SOURCE => Exif::SOURCE, - self::TITLE => Exif::TITLE, - self::ARTIST => Exif::AUTHOR, - self::MODEL => Exif::CAMERA, - self::COLORSPACE => Exif::COLORSPACE, - self::DATETIMEORIGINAL => Exif::CREATION_DATE, - self::EXPOSURETIME => Exif::EXPOSURE, - self::FILESIZE => Exif::FILESIZE, - self::FOCALLENGTH => Exif::FOCAL_LENGTH, - self::ISOSPEEDRATINGS => Exif::ISO, - self::MIMETYPE => Exif::MIMETYPE, - self::ORIENTATION => Exif::ORIENTATION, - self::SOFTWARE => Exif::SOFTWARE, - self::XRESOLUTION => Exif::HORIZONTAL_RESOLUTION, - self::YRESOLUTION => Exif::VERTICAL_RESOLUTION, - self::GPSLATITUDE => Exif::GPS, - self::GPSLONGITUDE => Exif::GPS, - ); - - /** - * Maps the array of raw source data to the correct - * fields for the \PHPExif\Exif class - * - * @param array $data - * @return array - */ - public function mapRawData(array $data) - { - $mappedData = array(); - $gpsData = array(); - foreach ($data as $field => $value) { - if ($this->isSection($field) && is_array($value)) { - $subData = $this->mapRawData($value); - - $mappedData = array_merge($mappedData, $subData); - continue; - } - - if (!array_key_exists($field, $this->map)) { - // silently ignore unknown fields - continue; - } - - $key = $this->map[$field]; - - // manipulate the value if necessary - switch ($field) { - case self::DATETIMEORIGINAL: - try { - $value = new DateTime($value); - } catch (Exception $exception) { - continue 2; - } - break; - case self::EXPOSURETIME: - if (!is_float($value)) { - $value = $this->normalizeComponent($value); - } - - // Based on the source code of Exiftool (PrintExposureTime subroutine): - // http://cpansearch.perl.org/src/EXIFTOOL/Image-ExifTool-9.90/lib/Image/ExifTool/Exif.pm - if ($value < 0.25001 && $value > 0) { - $value = sprintf('1/%d', intval(0.5 + 1 / $value)); - } else { - $value = sprintf('%.1f', $value); - $value = preg_replace('/.0$/', '', $value); - } - break; - case self::FOCALLENGTH: - $parts = explode('/', $value); - $value = (int) reset($parts) / (int) end($parts); - break; - case self::XRESOLUTION: - case self::YRESOLUTION: - $resolutionParts = explode('/', $value); - $value = (int) reset($resolutionParts); - break; - case self::GPSLATITUDE: - $gpsData['lat'] = $this->extractGPSCoordinate($value); - break; - case self::GPSLONGITUDE: - $gpsData['lon'] = $this->extractGPSCoordinate($value); - break; - } - - // set end result - $mappedData[$key] = $value; - } - - // add GPS coordinates, if available - if (count($gpsData) === 2) { - $latitudeRef = empty($data['GPSLatitudeRef'][0]) ? 'N' : $data['GPSLatitudeRef'][0]; - $longitudeRef = empty($data['GPSLongitudeRef'][0]) ? 'E' : $data['GPSLongitudeRef'][0]; - - $gpsLocation = sprintf( - '%s,%s', - (strtoupper($latitudeRef) === 'S' ? -1 : 1) * $gpsData['lat'], - (strtoupper($longitudeRef) === 'W' ? -1 : 1) * $gpsData['lon'] - ); - - $mappedData[Exif::GPS] = $gpsLocation; - } else { - unset($mappedData[Exif::GPS]); - } - - return $mappedData; - } - - /** - * Determines if given field is a section - * - * @param string $field - * @return bool - */ - protected function isSection($field) - { - return (in_array($field, $this->sections)); - } - - /** - * Extract GPS coordinates from components array - * - * @param array $components - * @return float - */ - protected function extractGPSCoordinate(array $components) - { - $components = array_map(array($this, 'normalizeComponent'), $components); - - if (count($components) > 2) { - return intval($components[0]) + (intval($components[1]) / 60) + (floatval($components[2]) / 3600); - } - - return reset($components); - } - - /** - * Normalize component - * - * @param mixed $component - * @return int|float - */ - protected function normalizeComponent($component) - { - $parts = explode('/', $component); - - if (count($parts) > 1) { - if ($parts[1]) { - return intval($parts[0]) / intval($parts[1]); - } - - return 0; - } - - return floatval(reset($parts)); - } -} diff --git a/lib/PHPExif/Reader/Reader.php b/lib/PHPExif/Reader/Reader.php deleted file mode 100755 index 34b7bb5..0000000 --- a/lib/PHPExif/Reader/Reader.php +++ /dev/null @@ -1,111 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Reader - */ - -namespace PHPExif\Reader; - -use PHPExif\Adapter\AdapterInterface; -use PHPExif\Adapter\NoAdapterException; -use PHPExif\Adapter\Exiftool as ExiftoolAdapter; -use PHPExif\Adapter\Native as NativeAdapter; - -/** - * PHP Exif Reader - * - * Responsible for all the read operations on a file's EXIF metadata - * - * @category PHPExif - * @package Reader - * @ - */ -class Reader implements ReaderInterface -{ - const TYPE_NATIVE = 'native'; - const TYPE_EXIFTOOL = 'exiftool'; - - /** - * The current adapter - * - * @var \PHPExif\Adapter\AdapterInterface - */ - protected $adapter; - - /** - * Reader constructor - * - * @param \PHPExif\Adapter\AdapterInterface $adapter - */ - public function __construct(AdapterInterface $adapter) - { - $this->adapter = $adapter; - } - - /** - * Getter for the reader adapter - * - * @return \PHPExif\Adapter\AdapterInterface - * @throws NoAdapterException When no adapter is set - */ - public function getAdapter() - { - if (empty($this->adapter)) { - throw new NoAdapterException('No adapter set in the reader'); - } - - return $this->adapter; - } - - /** - * Factory for the reader - * - * @param string $type - * @return $this - * @throws \InvalidArgumentException When given type is invalid - */ - public static function factory($type) - { - $classname = get_called_class(); - switch ($type) { - case self::TYPE_NATIVE: - $adapter = new NativeAdapter(); - break; - case self::TYPE_EXIFTOOL: - $adapter = new ExiftoolAdapter(); - break; - default: - throw new \InvalidArgumentException( - sprintf('Unknown type "%1$s"', $type) - ); - } - return new $classname($adapter); - } - - /** - * Reads & parses the EXIF data from given file - * - * @param string $file - * @return \PHPExif\Exif Instance of Exif object with data - */ - public function read($file) - { - return $this->getAdapter()->getExifFromFile($file); - } - - /** - * alias to read method - * - * @param string $file - * @return \PHPExif\Exif Instance of Exif object with data - */ - public function getExifFromFile($file) - { - return $this->read($file); - } -} diff --git a/lib/PHPExif/Reader/ReaderInterface.php b/lib/PHPExif/Reader/ReaderInterface.php deleted file mode 100644 index 9617396..0000000 --- a/lib/PHPExif/Reader/ReaderInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Reader - * @codeCoverageIgnore - */ - -namespace PHPExif\Reader; - -/** - * PHP Exif Reader - * - * Defines the interface for reader functionality - * - * @category PHPExif - * @package Reader - */ -interface ReaderInterface -{ - /** - * Reads & parses the EXIF data from given file - * - * @param string $file - * @return \PHPExif\Exif Instance of Exif object with data - */ - public function read($file); -} diff --git a/lib/PHPExif/Mapper/MapperInterface.php b/src/PHPExif/Adapter/MapperInterface.php similarity index 62% rename from lib/PHPExif/Mapper/MapperInterface.php rename to src/PHPExif/Adapter/MapperInterface.php index 5f5097e..ce624f9 100644 --- a/lib/PHPExif/Mapper/MapperInterface.php +++ b/src/PHPExif/Adapter/MapperInterface.php @@ -10,12 +10,15 @@ * @codeCoverageIgnore */ -namespace PHPExif\Mapper; +namespace PHPExif\Adapter; + +use PHPExif\Data\ExifInterface; /** - * PHP Exif Mapper + * MapperInterface * - * Defines the interface for data mappers + * Public API for mapping raw EXIF data + * to and from Exif * * @category PHPExif * @package Mapper @@ -27,7 +30,16 @@ interface MapperInterface * fields for the \PHPExif\Exif class * * @param array $data + * @return ExifInterface + */ + public function map(array $data); + + /** + * Maps the data of given Exif object + * to an array of raw data + * + * @param ExifInterface $exif * @return array */ - public function mapRawData(array $data); + public function serialize(ExifInterface $exif); } diff --git a/src/PHPExif/Adapter/Native/Reader/Configuration.php b/src/PHPExif/Adapter/Native/Reader/Configuration.php new file mode 100644 index 0000000..2cac869 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Reader/Configuration.php @@ -0,0 +1,119 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Adapter\Native\Reader; + +/** + * Configuration class + * + * @category PHPExif + * @package Exif + */ +final class Configuration +{ + const INCLUDE_THUMBNAIL = true; + const NO_THUMBNAIL = false; + + const SECTIONS_AS_ARRAYS = true; + const SECTIONS_FLAT = false; + + const SECTION_FILE = 'FILE'; + const SECTION_COMPUTED = 'COMPUTED'; + const SECTION_IFD0 = 'IFD0'; + const SECTION_THUMBNAIL = 'THUMBNAIL'; + const SECTION_COMMENT = 'COMMENT'; + const SECTION_EXIF = 'EXIF'; + const SECTION_ALL = 'ANY_TAG'; + const SECTION_IPTC = 'IPTC'; + + /** + * List of EXIF sections + * + * @var array + */ + private $requiredSections = array(); + + /** + * Include the thumbnail in the EXIF data? + * + * @var boolean + */ + public $includeThumbnail = self::NO_THUMBNAIL; + + /** + * Parse the sections as arrays? + * + * @var boolean + */ + public $sectionsAsArrays = self::SECTIONS_FLAT; + + /** + * Classname of the Mapper to use when mapping raw data + * to an Exif object + * + * @var string + */ + public $mapperClass = '\\PHPExif\\Adapter\\Native\\Mapper'; + + /** + * Getter for the EXIF sections + * + * @return array + */ + public function getRequiredSections() + { + return $this->requiredSections; + } + + /** + * Returns the required EXIF sections as + * a comma-separated string + * + * @return string + */ + public function getRequiredSectionsAsString() + { + if (empty($this->requiredSections)) { + return null; + } + + return implode(',', $this->requiredSections); + } + + /** + * Setter for the EXIF sections + * + * @param array $sections List of EXIF sections + * @return Configuration + */ + public function setRequiredSections(array $sections) + { + $this->requiredSections = $sections; + + return $this; + } + + /** + * Adds an EXIF section to the list + * + * @param string $section + * @return Configuration + */ + public function addRequiredSection($section) + { + if (!in_array($section, $this->requiredSections)) { + array_push($this->requiredSections, $section); + } + + return $this; + } +} diff --git a/src/PHPExif/Adapter/Native/Reader/Mapper.php b/src/PHPExif/Adapter/Native/Reader/Mapper.php new file mode 100644 index 0000000..86d0b29 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Reader/Mapper.php @@ -0,0 +1,379 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Adapter\Native\Mapper; + +use PHPExif\Adapter\MapperInterface; +use PHPExif\Data\Exif; +use PHPExif\Data\ExifInterface; +use PHPExif\Exception\InterruptException; + +/** + * Mapper class + * + * @category PHPExif + * @package Exif + */ +final class Mapper implements MapperInterface +{ + const APERTUREFNUMBER = 'ApertureFNumber'; + const ARTIST = 'Artist'; + const CAPTION = 'caption'; + const COLORSPACE = 'ColorSpace'; + const COPYRIGHT = 'copyright'; + const CREDIT = 'credit'; + const DATETIMEORIGINAL = 'DateTimeOriginal'; + const EXPOSURETIME = 'ExposureTime'; + const FILESIZE = 'FileSize'; + const FOCALLENGTH = 'FocalLength'; + const FOCUSDISTANCE = 'FocusDistance'; + const GPSLATITUDE = 'GPSLatitude'; + const GPSLONGITUDE = 'GPSLongitude'; + const HEADLINE = 'headline'; + const HEIGHT = 'Height'; + const ISOSPEEDRATINGS = 'ISOSpeedRatings'; + const JOBTITLE = 'jobtitle'; + const KEYWORDS = 'keywords'; + const MIMETYPE = 'MimeType'; + const MODEL = 'Model'; + const ORIENTATION = 'Orientation'; + const SOFTWARE = 'Software'; + const SOURCE = 'source'; + const TITLE = 'title'; + const WIDTH = 'Width'; + const XRESOLUTION = 'XResolution'; + const YRESOLUTION = 'YResolution'; + + const SECTION_ALL = 'ANY_TAG'; + const SECTION_COMMENT = 'COMMENT'; + const SECTION_COMPUTED = 'COMPUTED'; + const SECTION_EXIF = 'EXIF'; + const SECTION_FILE = 'FILE'; + const SECTION_IFD0 = 'IFD0'; + const SECTION_IPTC = 'IPTC'; + const SECTION_THUMBNAIL = 'THUMBNAIL'; + + /** + * A list of section names + * + * @var array + */ + private $sections = array( + self::SECTION_ALL, + self::SECTION_COMMENT, + self::SECTION_COMPUTED, + self::SECTION_EXIF, + self::SECTION_FILE, + self::SECTION_IFD0, + self::SECTION_IPTC, + self::SECTION_THUMBNAIL, + ); + + /** + * Maps the native fields to the fields of + * the \PHPExif\Data\Exif class + * + * @var array + */ + private $map = array( + self::APERTUREFNUMBER => ExifInterface::APERTURE, + self::ARTIST => ExifInterface::AUTHOR, + self::CAPTION => ExifInterface::CAPTION, + self::COLORSPACE => ExifInterface::COLORSPACE, + self::COPYRIGHT => ExifInterface::COPYRIGHT, + self::CREDIT => ExifInterface::CREDIT, + self::DATETIMEORIGINAL => ExifInterface::CREATION_DATE, + self::EXPOSURETIME => ExifInterface::EXPOSURE, + self::FILESIZE => ExifInterface::FILESIZE, + self::FOCALLENGTH => ExifInterface::FOCAL_LENGTH, + self::FOCUSDISTANCE => ExifInterface::FOCAL_DISTANCE, + self::GPSLATITUDE => ExifInterface::GPS, + self::GPSLONGITUDE => ExifInterface::GPS, + self::HEADLINE => ExifInterface::HEADLINE, + self::HEIGHT => ExifInterface::HEIGHT, + self::ISOSPEEDRATINGS => ExifInterface::ISO, + self::JOBTITLE => ExifInterface::JOB_TITLE, + self::KEYWORDS => ExifInterface::KEYWORDS, + self::MIMETYPE => ExifInterface::MIMETYPE, + self::MODEL => ExifInterface::CAMERA, + self::ORIENTATION => ExifInterface::ORIENTATION, + self::SOFTWARE => ExifInterface::SOFTWARE, + self::SOURCE => ExifInterface::SOURCE, + self::TITLE => ExifInterface::TITLE, + self::WIDTH => ExifInterface::WIDTH, + self::XRESOLUTION => ExifInterface::HORIZONTAL_RESOLUTION, + self::YRESOLUTION => ExifInterface::VERTICAL_RESOLUTION, + ); + + /** + * Maps a Native field to a method to manipulate the data + * for the \PHPExif\Data\Exif class + * + * @var array + */ + private $manipulators = array( + self::DATETIMEORIGINAL => 'convertDateTimeOriginal', + self::EXPOSURETIME => 'convertExposureTime', + self::FOCALLENGTH => 'convertFocalLength', + self::GPSLATITUDE => 'extractGPSCoordinate', + self::GPSLONGITUDE => 'extractGPSCoordinate', + self::XRESOLUTION => 'convertResolution', + self::YRESOLUTION => 'convertResolution', + ); + + /** + * {@inheritDoc} + */ + public function map(array $data) + { + $mappedData = array(); + foreach ($data as $field => $value) { + try { + $this->handleSection($field, $value, $mappedData); + $this->skipUnknownField($field); + $this->doCustomManipulation($field, $value) + } catch (InterruptException $e) { + continue; + } + + // set end result + $key = $this->map[$field]; + $mappedData[$key] = $value; + } + + $mappedData = $this->mapGPSData($data, $mappedData); + + $exif = new Exif($mappedData); + + return $exif; + } + + /** + * {@inheritDoc} + */ + public function serialize(ExifInterface $exif) + { + } + + /** + * Maps section data and merges it into the list of mapped data + * + * @param string $field + * @param string $value + * @param array $mappedData + * @throws InterruptException + */ + private function handleSection($field, $value, array &$mappedData) + { + if (!($this->isSection($field) && is_array($value))) { + return; + } + + $subData = $this->map($value); + $mappedData = array_merge( + $mappedData, + $subData + ); + + throw new InterruptException(); + } + + /** + * Determines if given field is known for mapping + * + * @param string $field + * @throws InterruptException + */ + private function skipUnknownField($field) + { + if (array_key_exists($field, $this->map)) { + return; + } + + throw new InterruptException(); + } + + /** + * Executes the custom manipulators if necessary + * + * @param string $field + * @param mixed $value + * @throws InterruptException + */ + private function doCustomManipulation($field, &$value) + { + if (!array_key_exists($field, $this->manipulators)) { + return; + } + + $method = $this->manipulators[$field]; + $value = $this->$method($value); + + if (null === $value) { + throw new InterruptException(); + } + } + + /** + * Maps GPS data to the correct key, if such data exists + * + * @param array $data + * @param array $mappedData + * @return array + */ + private function mapGPSData(array $data, array $mappedData) + { + if (!array_key_exists(self::GPSLATITUDE, $mappedData)) { + return $mappedData; + } + $gpsLocation = sprintf( + '%s,%s', + (strtoupper($data['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $mappedData[self::GPSLATITUDE], + (strtoupper($data['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $mappedData[self::GPSLONGITUDE] + ); + unset($mappedData[self::GPSLATITUDE]); + unset($mappedData[self::GPSLONGITUDE]); + $mappedData[Exif::GPS] = $gpsLocation; + return $mappedData; + } + + /** + * Determines if given field is a section + * + * @param string $field + * @return bool + */ + private function isSection($field) + { + return (in_array($field, $this->sections)); + } + + /** + * Converts incoming Native date to a DateTime object + * + * @param string $originalValue + * @return \DateTime + */ + private function convertDateTimeOriginal($originalValue) + { + try { + $originalValue = new DateTime($originalValue); + } catch (Exception $exception) { + return; + } + + return $originalValue; + } + + /** + * Converts incoming exposure time to a sensible format + * + * @param string $originalValue + * @return string + */ + private function convertExposureTime($originalValue) + { + if (!is_float($originalValue)) { + $originalValue = $this->normalizeComponent($value); + } + + // Based on the source code of Exiftool (PrintExposureTime subroutine): + // http://cpansearch.perl.org/src/EXIFTOOL/Image-ExifTool-9.90/lib/Image/ExifTool/Exif.pm + if ($originalValue < 0.25001 && $originalValue > 0) { + return sprintf( + '1/%d', + intval(0.5 + 1 / $originalValue) + ); + } + + $originalValue = sprintf('%.1f', $originalValue); + return preg_replace('/.0$/', '', $originalValue); + } + + /** + * Converts focal length to a float value + * + * @param string $originalValue + * @return float + */ + private function convertFocalLength($originalValue) + { + $parts = explode('/', $originalValue); + return ((int) reset($parts) / (int) end($parts)); + } + + /** + * Converts incoming resolution value to a sensible value + * + * @param string $originalValue + * @return int + */ + private function convertResolution($originalValue) + { + $resolutionParts = explode('/', $originalValue); + return ((int) reset($resolutionParts)); + } + + /** + * Extract GPS coordinates from components array + * + * @param array $components + * @return float + */ + private function extractGPSCoordinate(array $components) + { + $components = array_map( + array($this, 'normalizeGPSComponent'), + $components + ); + + if (count($components) > 2) { + return intval($components[0]) + (intval($components[1]) / 60) + (floatval($components[2]) / 3600); + } + + return reset($components); + } + + /** + * Normalize GPS coordinates components + * + * @param mixed $component + * @return int|float + */ + private function normalizeGPSComponent($component) + { + $parts = explode('/', $component); + return count($parts) === 1 ? $parts[0] : (int) reset($parts) / (int) end($parts); + } + + /** + * Normalize component + * + * @param mixed $component + * @return int|float + */ + private function normalizeComponent($component) + { + $parts = explode('/', $component); + + if (count($parts) > 1) { + if ($parts[1]) { + return intval($parts[0]) / intval($parts[1]); + } + + return 0; + } + + return floatval(reset($parts)); + } +} diff --git a/src/PHPExif/Adapter/Native/Reader/Reader.php b/src/PHPExif/Adapter/Native/Reader/Reader.php new file mode 100644 index 0000000..bfc2caf --- /dev/null +++ b/src/PHPExif/Adapter/Native/Reader/Reader.php @@ -0,0 +1,138 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Adapter\Native\Reader; + +use PHPExif\Adapter\MapperInterface; +use PHPExif\Adapter\ReaderInterface; +use PHPExif\Data\Exif; +use PHPExif\Data\Iptc; +use PHPExif\Data\IptcInterface; +use PHPExif\Exception\NoExifDataException; +use PHPExif\Exception\UnknownAdapterTypeException; + +/** + * Reader class + * + * @category PHPExif + * @package Exif + */ +final class Reader implements ReaderInterface +{ + /** + * @var Configuration + */ + private $configuration; + + /** + * @param Configuration $configuration + */ + public function __construct(Configuration $configuration) + { + $this->configuration = $configuration; + } + + /** + * Returns an instance with sane defaults + * everyone can agree on + * + * @return Reader + */ + public static function withDefaults() + { + $configuration = new Configuration(); + $instance = new Reader($configuration); + + return $instance; + } + + /** + * Returns an instance of the configured mapper class + * + * @return MapperInterface + * @throws UnknownAdapterTypeException + */ + public function getMapper() + { + $mapper = new $this->configuration->mapperClass; + + if (!$mapper instanceof MapperInterface) { + throw UnknownAdapterTypeException::noInterface( + $this->configuration->mapperClass, + 'PHPExif\\Adapter\\MapperInterface' + ); + } + + return $mapper; + } + + /** + * {@inheritDoc} + * @throws NoExifDataException + */ + public function read($filePath) + { + $data = @exif_read_data( + $filePath, + $this->configuration->getRequiredSectionsAsString(), + $this->configuration->sectionsAsArrays, + $this->configuration->includeThumbnail + ); + + if (false === $data) { + throw NoExifDataException::fromFile($filePath); + } + + $iptc = $this->getIptcData($file); + $data = array_merge( + $data, + array( + Configuration::SECTION_IPTC => $iptc->toArray(), + ) + ); + + // map the data: + $mapper = $this->getMapper(); + $exif = $mapper->map($data); + + return $exif; + } + + /** + * Returns an array of IPTC data + * + * @param string $file The file to read the IPTC data from + * @return IptcInterface + */ + private function getIptcData($file) + { + getimagesize($file, $info); + $arrData = array(); + if (isset($info['APP13'])) { + $iptc = iptcparse($info['APP13']); + + foreach (Iptc::$iptcMapping as $name => $field) { + if (!isset($iptc[$field])) { + continue; + } + + $value = $iptc[$field]; + if (count($value) === 1) { + $value = reset($value); + } + $arrData[$name] = $value; + } + } + + return new Iptc($arrData); + } +} diff --git a/src/PHPExif/Adapter/ReaderInterface.php b/src/PHPExif/Adapter/ReaderInterface.php new file mode 100644 index 0000000..a52d9c8 --- /dev/null +++ b/src/PHPExif/Adapter/ReaderInterface.php @@ -0,0 +1,33 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Adapter; + +use PHPExif\Data\ExifInterface; + +/** + * ReaderInterface + * + * Public API for reading EXIF data + * + * @category PHPExif + * @package Exif + */ +interface ReaderInterface +{ + /** + * Read the EXIF metadata of given file + * + * @param string $filePath + * @return ExifInterface + */ + public function read($filePath); +} diff --git a/lib/PHPExif/Adapter/NoAdapterException.php b/src/PHPExif/Data/Exif.php similarity index 50% rename from lib/PHPExif/Adapter/NoAdapterException.php rename to src/PHPExif/Data/Exif.php index 8a2b011..45b6803 100644 --- a/lib/PHPExif/Adapter/NoAdapterException.php +++ b/src/PHPExif/Data/Exif.php @@ -1,28 +1,30 @@ * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Reader - * @codeCoverageIgnore + * @package Exif */ -namespace PHPExif\Adapter; - -use Exception; +namespace PHPExif\Data; /** - * PHP Exif Reader Adapter + * Exif class * - * Defines the interface for reader adapters + * Container for EXIF data * * @category PHPExif - * @package Reader + * @package Exif */ -class NoAdapterException extends Exception +final class Exif implements ExifInterface { - //empty + /** + * @param array $rawData + */ + public function __construct(array $data) + { + } } diff --git a/src/PHPExif/Data/ExifInterface.php b/src/PHPExif/Data/ExifInterface.php new file mode 100644 index 0000000..9eaed65 --- /dev/null +++ b/src/PHPExif/Data/ExifInterface.php @@ -0,0 +1,50 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +/** + * ExifInterface + * + * Public API for EXIF data + * + * @category PHPExif + * @package Exif + */ +interface ExifInterface +{ + const APERTURE = 'aperture'; + const AUTHOR = 'author'; + const CAMERA = 'camera'; + const CAPTION = 'caption'; + const COLORSPACE = 'ColorSpace'; + const COPYRIGHT = 'copyright'; + const CREATION_DATE = 'creationdate'; + const CREDIT = 'credit'; + const EXPOSURE = 'exposure'; + const FILESIZE = 'FileSize'; + const FOCAL_LENGTH = 'focalLength'; + const FOCAL_DISTANCE = 'focalDistance'; + const HEADLINE = 'headline'; + const HEIGHT = 'height'; + const HORIZONTAL_RESOLUTION = 'horizontalResolution'; + const ISO = 'iso'; + const JOB_TITLE = 'jobTitle'; + const KEYWORDS = 'keywords'; + const MIMETYPE = 'MimeType'; + const ORIENTATION = 'Orientation'; + const SOFTWARE = 'software'; + const SOURCE = 'source'; + const TITLE = 'title'; + const VERTICAL_RESOLUTION = 'verticalResolution'; + const WIDTH = 'width'; + const GPS = 'gps'; +} diff --git a/src/PHPExif/Data/Iptc.php b/src/PHPExif/Data/Iptc.php new file mode 100644 index 0000000..4e52119 --- /dev/null +++ b/src/PHPExif/Data/Iptc.php @@ -0,0 +1,266 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +/** + * Iptc class + * + * Container for IPTC data + * + * @category PHPExif + * @package Exif + */ +final class Iptc implements IptcInterface +{ + /** + * @var string + */ + private $caption; + + /** + * @var string + */ + private $copyright; + + /** + * @var string + */ + private $credit; + + /** + * @var string + */ + private $headline; + + /** + * @var string + */ + private $jobtitle; + + /** + * @var array + */ + private $keywords = array(); + + /** + * @var string + */ + private $source; + + /** + * @var string + */ + private $title; + + /** + * Contains the mapping of names to IPTC field numbers + * + * @var array + */ + public static $iptcMapping = array( + 'caption' => '2#120', + 'copyright' => '2#116', + 'credit' => '2#110', + 'headline' => '2#105', + 'jobtitle' => '2#085', + 'keywords' => '2#025', + 'source' => '2#115', + 'title' => '2#005', + ); + + /** + * @param array $data + */ + public function __construct(array $data) + { + foreach ($data as $key => $value) { + if (!array_key_exists($key, $this->iptcMapping)) { + continue; + } + + $this->$key = $value; + } + } + + /** + * {@inheritDoc} + */ + public function toArray($withEmpty = true) + { + $data = array(); + $keys = array_keys($this->iptcMapping); + foreach ($keys as $prop) { + $accessor = 'get' . ucfirst($prop); + $value = $this->$accessor(); + + if (empty($value) && !$withEmpty) { + continue; + } + + $data[$prop] = $value; + } + + return $data; + } + + /** + * {@inheritDoc} + */ + public function getCaption() + { + return $this->caption; + } + + /** + * {@inheritDoc} + */ + public function withCaption($caption) + { + $new = clone $this; + $new->caption = $caption; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getCopyright() + { + return $this->copyright; + } + + /** + * {@inheritDoc} + */ + public function withCopyright($copyright) + { + $new = clone $this; + $new->copyright = $copyright; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getCredit() + { + return $this->credit; + } + + /** + * {@inheritDoc} + */ + public function withCredit($credit) + { + $new = clone $this; + $new->credit = $credit; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getHeadline() + { + return $this->headline; + } + + /** + * {@inheritDoc} + */ + public function withHeadline($headline) + { + $new = clone $this; + $new->headline = $headline; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getJobtitle() + { + return $this->jobtitle; + } + + /** + * {@inheritDoc} + */ + public function withJobtitle($jobitle) + { + $new = clone $this; + $new->jobtitle = $jobtitle; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getKeywords() + { + return $this->keywords; + } + + /** + * {@inheritDoc} + */ + public function withKeywords(array $keywords) + { + $new = clone $this; + $new->keywords = $keywords; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getSource() + { + return $this->source; + } + + /** + * {@inheritDoc} + */ + public function withSource($source) + { + $new = clone $this; + $new->source = $source; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getTitle() + { + return $this->title; + } + + /** + * {@inheritDoc} + */ + public function withTitle($title) + { + $new = clone $this; + $new->title = $title; + + return $new; + } +} diff --git a/src/PHPExif/Data/IptcInterface.php b/src/PHPExif/Data/IptcInterface.php new file mode 100644 index 0000000..dbf2f8d --- /dev/null +++ b/src/PHPExif/Data/IptcInterface.php @@ -0,0 +1,151 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +/** + * IptcInterface + * + * Public API for IPTC data + * + * @category PHPExif + * @package Exif + */ +interface IptcInterface +{ + /** + * Array represenation of current instance + * + * @param boolean $withEmpty + * @return array + */ + public function toArray($withEmpty = true); + + /** + * Accessor for the caption + * + * @return string + */ + public function getCaption(); + + /** + * Returns new instance with updated caption + * + * @param string $caption + * @return IptcInterface + */ + public function withCaption($caption); + + /** + * Accessor for the copyright + * + * @return string + */ + public function getCopyright(); + + /** + * Returns new instance with updated copyright + * + * @param string $copyright + * @return IptcInterface + */ + public function withCopyright($copyright); + + /** + * Accessor for the credit + * + * @return string + */ + public function getCredit(); + + /** + * Returns new instance with updated credit + * + * @param string $credit + * @return IptcInterface + */ + public function withCredit($credit); + + /** + * Accessor for the headline + * + * @return string + */ + public function getHeadline(); + + /** + * Returns new instance with updated headline + * + * @param string $headline + * @return IptcInterface + */ + public function withHeadline($headline); + + /** + * Accessor for the jobtitle + * + * @return string + */ + public function getJobtitle(); + + /** + * Returns new instance with updated jobtitle + * + * @param string $jobtitle + * @return IptcInterface + */ + public function withJobtitle($jobitle); + + /** + * Accessor for the keywords + * + * @return array + */ + public function getKeywords(); + + /** + * Returns new instance with updated keywords + * + * @param string $keywords + * @return IptcInterface + */ + public function withKeywords(array $keywords); + + /** + * Accessor for the source + * + * @return string + */ + public function getSource(); + + /** + * Returns new instance with updated source + * + * @param string $source + * @return IptcInterface + */ + public function withSource($source); + + /** + * Accessor for the title + * + * @return string + */ + public function getTitle(); + + /** + * Returns new instance with updated title + * + * @param string $title + * @return IptcInterface + */ + public function withTitle($title); +} diff --git a/src/PHPExif/Exception/InteruptException.php b/src/PHPExif/Exception/InteruptException.php new file mode 100644 index 0000000..6e5ece3 --- /dev/null +++ b/src/PHPExif/Exception/InteruptException.php @@ -0,0 +1,22 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Exception; + +/** + * InterruptException class + * + * @category PHPExif + * @package Exif + */ +class InterruptException extends \Exception +{ +} diff --git a/src/PHPExif/Exception/NoExifDataException.php b/src/PHPExif/Exception/NoExifDataException.php new file mode 100644 index 0000000..14b94a1 --- /dev/null +++ b/src/PHPExif/Exception/NoExifDataException.php @@ -0,0 +1,37 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Exception; + +/** + * Reader class + * + * @category PHPExif + * @package Exif + */ +class NoExifDataException extends \Exception +{ + /** + * Could not read EXIF data from given path + * + * @param string $path + * @return NoExifDataException + */ + public static function fromFile($path) + { + return new self( + sprintf( + 'Could not read EXIF data from file %1$s', + $path + ) + ); + } +} diff --git a/src/PHPExif/Exception/UnknownAdapterTypeException.php b/src/PHPExif/Exception/UnknownAdapterTypeException.php new file mode 100644 index 0000000..decc1ef --- /dev/null +++ b/src/PHPExif/Exception/UnknownAdapterTypeException.php @@ -0,0 +1,55 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Exception; + +/** + * UnknownAdapterTypeException class + * + * @category PHPExif + * @package Exif + */ +class UnknownAdapterTypeException extends \Exception +{ + /** + * No adapter set in the reader + * + * @param string $type + * @return UnknownAdapterTypeException + */ + public static function forType($type) + { + return new self( + sprintf( + 'Unknown adapter type "%1$s"', + $type + ) + ); + } + + /** + * Not an instance of the MapperInterface + * + * @param string $classname + * @param string $interfaceName + * @return UnknownAdapterTypeException + */ + public static function noInterface($classname, $interfaceName) + { + return new self( + sprintf( + 'Class "%1$s" does not implement %2$s', + $classname, + $interfaceName + ) + ); + } +} diff --git a/src/PHPExif/Reader.php b/src/PHPExif/Reader.php new file mode 100644 index 0000000..aad6dfb --- /dev/null +++ b/src/PHPExif/Reader.php @@ -0,0 +1,93 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +use PHPExif\Adapter\Native\Reader\Reader as NativeReader; +use PHPExif\Exception\NoAdapterException; +use PHPExif\Exception\UnknownAdapterTypeException; + +/** + * Reader class + * + * Responsible for reading EXIF data from a file + * + * @category PHPExif + * @package Exif + */ +final class Reader +{ + const TYPE_NATIVE = 'native'; + const TYPE_EXIFTOOL = 'exiftool'; + + /** + * The current adapter + * + * @var \PHPExif\Adapter\ReaderInterface + */ + private $adapter; + + /** + * Reader constructor + * + * @param \PHPExif\Adapter\ReaderInterface $adapter + */ + public function __construct(ReaderInterface $adapter) + { + $this->adapter = $adapter; + } + + /** + * Getter for the reader adapter + * + * @return \PHPExif\Adapter\ReaderInterface + */ + public function getAdapter() + { + return $this->adapter; + } + + /** + * Factory for the reader + * + * @param string $type + * @return Reader + * @throws UnknownAdapterTypeException When given type is invalid + */ + public static function factory($type) + { + $classname = get_called_class(); + switch ($type) { + case self::TYPE_NATIVE: + $adapter = NativeReader::withDefaults(); + break; + /* + case self::TYPE_EXIFTOOL: + $adapter = new ExiftoolAdapter(); + break; + */ + default: + throw UnknownAdapterTypeException::forType($type); + } + return new $classname($adapter); + } + + /** + * Reads & parses the EXIF data from given file + * + * @param string $file + * @return \PHPExif\Data\Exif + */ + public function read($file) + { + return $this->getAdapter()->read($file); + } +} diff --git a/tests/PHPExif/Adapter/AdapterAbstractTest.php b/tests/PHPExif/Adapter/AdapterAbstractTest.php deleted file mode 100644 index 46982da..0000000 --- a/tests/PHPExif/Adapter/AdapterAbstractTest.php +++ /dev/null @@ -1,232 +0,0 @@ - - * @covers \PHPExif\Adapter\AdapterInterface - */ -class AdapterAbstractTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \PHPExif\Adapter\Exiftool|\PHPExif\Adapter\Native - */ - protected $adapter; - - public function setUp() - { - $this->adapter = new \PHPExif\Adapter\Native(); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::setOptions - */ - public function testSetOptionsReturnsCurrentInstance() - { - $result = $this->adapter->setOptions(array()); - $this->assertSame($this->adapter, $result); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::setOptions - */ - public function testSetOptionsCorrectlySetsProperties() - { - $expected = array( - 'requiredSections' => array('foo', 'bar', 'baz',), - 'includeThumbnail' => \PHPExif\Adapter\Native::INCLUDE_THUMBNAIL, - 'sectionsAsArrays' => \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS, - ); - $this->adapter->setOptions($expected); - - foreach ($expected as $key => $value) { - $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key); - $reflProp->setAccessible(true); - $this->assertEquals($value, $reflProp->getValue($this->adapter)); - } - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::setOptions - */ - public function testSetOptionsIgnoresPropertiesWithoutSetters() - { - $expected = array( - 'iptcMapping' => array('foo', 'bar', 'baz'), - ); - $this->adapter->setOptions($expected); - - foreach ($expected as $key => $value) { - $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key); - $reflProp->setAccessible(true); - $this->assertNotEquals($value, $reflProp->getValue($this->adapter)); - } - } - - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::__construct - */ - public function testConstructorSetsOptions() - { - $expected = array( - 'requiredSections' => array('foo', 'bar', 'baz',), - 'includeThumbnail' => \PHPExif\Adapter\Native::INCLUDE_THUMBNAIL, - 'sectionsAsArrays' => \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS, - ); - $adapter = new \PHPExif\Adapter\Native($expected); - - foreach ($expected as $key => $value) { - $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key); - $reflProp->setAccessible(true); - $this->assertEquals($value, $reflProp->getValue($adapter)); - } - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::setMapper - */ - public function testSetMapperReturnsCurrentInstance() - { - $mapper = new \PHPExif\Mapper\Native(); - $result = $this->adapter->setMapper($mapper); - $this->assertSame($this->adapter, $result); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::setMapper - */ - public function testSetMapperCorrectlySetsInProperty() - { - $mapper = new \PHPExif\Mapper\Native(); - $this->adapter->setMapper($mapper); - - $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\AdapterAbstract', 'mapper'); - $reflProp->setAccessible(true); - $this->assertSame($mapper, $reflProp->getValue($this->adapter)); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getMapper - */ - public function testGetMapperCorrectlyReturnsFromProperty() - { - $mapper = new \PHPExif\Mapper\Native(); - $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\AdapterAbstract', 'mapper'); - $reflProp->setAccessible(true); - $reflProp->setValue($this->adapter, $mapper); - $this->assertSame($mapper, $this->adapter->getMapper()); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getMapper - */ - public function testGetMapperLazyLoadsMapperWhenNotPresent() - { - $reflProp = new \ReflectionProperty( - get_class($this->adapter), - 'mapperClass' - ); - - $mapperClass = '\\PHPExif\\Mapper\\Native'; - $reflProp->setAccessible(true); - $reflProp->setValue($this->adapter, $mapperClass); - - $this->assertInstanceOf($mapperClass, $this->adapter->getMapper()); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getMapper - */ - public function testGetMapperLazyLoadingSetsInProperty() - { - $reflProp = new \ReflectionProperty( - get_class($this->adapter), - 'mapperClass' - ); - - $mapperClass = '\\PHPExif\\Mapper\\Native'; - $reflProp->setAccessible(true); - $reflProp->setValue($this->adapter, $mapperClass); - - $reflProp2 = new \ReflectionProperty( - get_class($this->adapter), - 'mapper' - ); - $reflProp2->setAccessible(true); - $this->adapter->getMapper(); - $this->assertInstanceOf($mapperClass, $reflProp2->getValue($this->adapter)); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::setHydrator - */ - public function testSetHydratorReturnsCurrentInstance() - { - $hydrator = new \PHPExif\Hydrator\Mutator(); - $result = $this->adapter->setHydrator($hydrator); - $this->assertSame($this->adapter, $result); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::setHydrator - */ - public function testSetHydratorCorrectlySetsInProperty() - { - $hydrator = new \PHPExif\Hydrator\Mutator(); - $this->adapter->setHydrator($hydrator); - - $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\AdapterAbstract', 'hydrator'); - $reflProp->setAccessible(true); - $this->assertSame($hydrator, $reflProp->getValue($this->adapter)); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getHydrator - */ - public function testGetHydratorCorrectlyReturnsFromProperty() - { - $hydrator = new \PHPExif\Hydrator\Mutator(); - $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\AdapterAbstract', 'hydrator'); - $reflProp->setAccessible(true); - $reflProp->setValue($this->adapter, $hydrator); - $this->assertSame($hydrator, $this->adapter->getHydrator()); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getHydrator - */ - public function testGetHydratorLazyLoadsHydratorWhenNotPresent() - { - $hydratorClass = '\\PHPExif\\Hydrator\\Mutator'; - $this->assertInstanceOf($hydratorClass, $this->adapter->getHydrator()); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getHydrator - */ - public function testGetHydratorLazyLoadingSetsInProperty() - { - $hydratorClass = '\\PHPExif\\Hydrator\\Mutator'; - - $reflProp = new \ReflectionProperty( - get_class($this->adapter), - 'hydrator' - ); - $reflProp->setAccessible(true); - $this->adapter->getHydrator(); - $this->assertInstanceOf($hydratorClass, $reflProp->getValue($this->adapter)); - } -} - diff --git a/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php b/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php deleted file mode 100644 index 9d9bd39..0000000 --- a/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php +++ /dev/null @@ -1,68 +0,0 @@ - - */ - class ExiftoolProcOpenTest extends \PHPUnit_Framework_TestCase - { - /** - * @var \PHPExif\Adapter\Exiftool - */ - protected $adapter; - - public function setUp() - { - global $mockProcOpen; - $mockProcOpen = true; - $this->adapter = new \PHPExif\Adapter\Exiftool(); - } - - public function tearDown() - { - global $mockProcOpen; - $mockProcOpen = false; - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::getCliOutput - * @expectedException RuntimeException - */ - public function testGetCliOutput() - { - $reflMethod = new \ReflectionMethod('\PHPExif\Adapter\Exiftool', 'getCliOutput'); - $reflMethod->setAccessible(true); - - $result = $reflMethod->invoke( - $this->adapter, - sprintf( - '%1$s', - 'pwd' - ) - ); - } - } -} diff --git a/tests/PHPExif/Adapter/ExiftoolTest.php b/tests/PHPExif/Adapter/ExiftoolTest.php deleted file mode 100644 index 71abd2a..0000000 --- a/tests/PHPExif/Adapter/ExiftoolTest.php +++ /dev/null @@ -1,113 +0,0 @@ - - */ -class ExiftoolTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \PHPExif\Adapter\Exiftool - */ - protected $adapter; - - public function setUp() - { - $this->adapter = new \PHPExif\Adapter\Exiftool(); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::getToolPath - */ - public function testGetToolPathFromProperty() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Exiftool', 'toolPath'); - $reflProperty->setAccessible(true); - $expected = '/foo/bar/baz'; - $reflProperty->setValue($this->adapter, $expected); - - $this->assertEquals($expected, $this->adapter->getToolPath()); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::setToolPath - */ - public function testSetToolPathInProperty() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Exiftool', 'toolPath'); - $reflProperty->setAccessible(true); - - $expected = '/tmp'; - $this->adapter->setToolPath($expected); - - $this->assertEquals($expected, $reflProperty->getValue($this->adapter)); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::setToolPath - * @expectedException InvalidArgumentException - */ - public function testSetToolPathThrowsException() - { - $this->adapter->setToolPath('/foo/bar'); - } - - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::getToolPath - */ - public function testGetToolPathLazyLoadsPath() - { - $this->assertInternalType('string', $this->adapter->getToolPath()); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::setNumeric - */ - public function testSetNumericInProperty() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Exiftool', 'numeric'); - $reflProperty->setAccessible(true); - - $expected = true; - $this->adapter->setNumeric($expected); - - $this->assertEquals($expected, $reflProperty->getValue($this->adapter)); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::getExifFromFile - */ - public function testGetExifFromFile() - { - $file = PHPEXIF_TEST_ROOT . '/files/morning_glory_pool_500.jpg'; - $result = $this->adapter->getExifFromFile($file); - $this->assertInstanceOf('\PHPExif\Exif', $result); - $this->assertInternalType('array', $result->getRawData()); - $this->assertNotEmpty($result->getRawData()); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::getCliOutput - */ - public function testGetCliOutput() - { - $reflMethod = new \ReflectionMethod('\PHPExif\Adapter\Exiftool', 'getCliOutput'); - $reflMethod->setAccessible(true); - - $result = $reflMethod->invoke( - $this->adapter, - sprintf( - '%1$s', - 'pwd' - ) - ); - - $this->assertInternalType('string', $result); - } -} diff --git a/tests/PHPExif/Adapter/NativeTest.php b/tests/PHPExif/Adapter/NativeTest.php deleted file mode 100755 index 7dd86b6..0000000 --- a/tests/PHPExif/Adapter/NativeTest.php +++ /dev/null @@ -1,185 +0,0 @@ - - */ -class NativeTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \PHPExif\Adapter\Native - */ - protected $adapter; - - public function setUp() - { - $this->adapter = new \PHPExif\Adapter\Native(); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::setIncludeThumbnail - */ - public function testSetIncludeThumbnailInProperty() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'includeThumbnail'); - $reflProperty->setAccessible(true); - - $this->assertEquals(\PHPExif\Adapter\Native::NO_THUMBNAIL, $reflProperty->getValue($this->adapter)); - - $this->adapter->setIncludeThumbnail(\PHPExif\Adapter\Native::INCLUDE_THUMBNAIL); - - $this->assertEquals(\PHPExif\Adapter\Native::INCLUDE_THUMBNAIL, $reflProperty->getValue($this->adapter)); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::getIncludeThumbnail - */ - public function testGetIncludeThumbnailFromProperty() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'includeThumbnail'); - $reflProperty->setAccessible(true); - $reflProperty->setValue($this->adapter, \PHPExif\Adapter\Native::INCLUDE_THUMBNAIL); - - $this->assertEquals(\PHPExif\Adapter\Native::INCLUDE_THUMBNAIL, $this->adapter->getIncludeThumbnail()); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::GetIncludeThumbnail - */ - public function testGetIncludeThumbnailHasDefaultValue() - { - $this->assertEquals(\PHPExif\Adapter\Native::NO_THUMBNAIL, $this->adapter->getIncludeThumbnail()); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::getRequiredSections - */ - public function testGetRequiredSections() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'requiredSections'); - $reflProperty->setAccessible(true); - - $this->assertEquals($reflProperty->getValue($this->adapter), $this->adapter->getRequiredSections()); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::setRequiredSections - */ - public function testSetRequiredSections() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'requiredSections'); - $reflProperty->setAccessible(true); - - $testData = array('foo', 'bar', 'baz'); - - $returnValue = $this->adapter->setRequiredSections($testData); - - $this->assertEquals($testData, $reflProperty->getValue($this->adapter)); - $this->assertEquals($this->adapter, $returnValue); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::addRequiredSection - */ - public function testAddRequiredSection() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'requiredSections'); - $reflProperty->setAccessible(true); - - $testData = array('foo', 'bar', 'baz'); - $this->adapter->setRequiredSections($testData); - - $returnValue = $this->adapter->addRequiredSection('test'); - array_push($testData, 'test'); - - $this->assertEquals($testData, $reflProperty->getValue($this->adapter)); - $this->assertEquals($this->adapter, $returnValue); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::getExifFromFile - * @expectedException RuntimeException - */ - public function testGetExifFromFileNoData() - { - $file = PHPEXIF_TEST_ROOT . '/files/empty.jpg'; - $this->adapter->getExifFromFile($file); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::getExifFromFile - */ - public function testGetExifFromFileHasData() - { - $file = PHPEXIF_TEST_ROOT . '/files/morning_glory_pool_500.jpg'; - $result = $this->adapter->getExifFromFile($file); - $this->assertInstanceOf('\PHPExif\Exif', $result); - $this->assertInternalType('array', $result->getRawData()); - $this->assertNotEmpty($result->getRawData()); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::getIptcData - */ - public function testGetIptcData() - { - $file = PHPEXIF_TEST_ROOT . '/files/morning_glory_pool_500.jpg'; - $result = $this->adapter->getIptcData($file); - $expected = array( - 'title' => 'Morning Glory Pool', - 'keywords' => array( - '18-200', 'D90', 'USA', 'Wyoming', 'Yellowstone' - ), - ); - - $this->assertEquals($expected, $result); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::setSectionsAsArrays - */ - public function testSetSectionsAsArrayInProperty() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'sectionsAsArrays'); - $reflProperty->setAccessible(true); - $expected = \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS; - $this->adapter->setSectionsAsArrays($expected); - $actual = $reflProperty->getValue($this->adapter); - $this->assertEquals($expected, $actual); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::setSectionsAsArrays - */ - public function testSetSectionsAsArrayConvertsToBoolean() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'sectionsAsArrays'); - $reflProperty->setAccessible(true); - $expected = \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS; - $this->adapter->setSectionsAsArrays('Foo'); - $actual = $reflProperty->getValue($this->adapter); - $this->assertEquals($expected, $actual); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::getSectionsAsArrays - */ - public function testGetSectionsAsArrayFromProperty() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Native', 'sectionsAsArrays'); - $reflProperty->setAccessible(true); - $reflProperty->setValue($this->adapter, \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS); - - $this->assertEquals(\PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS, $this->adapter->getSectionsAsArrays()); - } -} diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php deleted file mode 100755 index 5191814..0000000 --- a/tests/PHPExif/ExifTest.php +++ /dev/null @@ -1,639 +0,0 @@ - - */ -class ExifTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \PHPExif\Exif - */ - protected $exif; - - /** - * Setup function before the tests - */ - public function setUp() - { - $this->exif = new \PHPExif\Exif(); - } - - /** - * @group exif - * @covers \PHPExif\Exif::__construct - */ - public function testConstructorCallsSetData() - { - $input = array(); - - // Get mock, without the constructor being called - $mock = $this->getMockBuilder('\\PHPExif\\Exif') - ->disableOriginalConstructor() - ->getMock(); - - // set expectations for constructor calls - $mock->expects($this->once()) - ->method('setData') - ->with( - $this->equalTo($input) - ); - - // now call the constructor - $reflectedClass = new ReflectionClass('\\PHPExif\\Exif'); - $constructor = $reflectedClass->getConstructor(); - $constructor->invoke($mock, $input); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getRawData - */ - public function testGetRawData() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Exif', 'rawData'); - $reflProperty->setAccessible(true); - - $this->assertEquals($reflProperty->getValue($this->exif), $this->exif->getRawData()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::setRawData - */ - public function testSetRawData() - { - $testData = array('foo', 'bar', 'baz'); - $reflProperty = new \ReflectionProperty('\PHPExif\Exif', 'rawData'); - $reflProperty->setAccessible(true); - - $result = $this->exif->setRawData($testData); - - $this->assertEquals($testData, $reflProperty->getValue($this->exif)); - $this->assertEquals($this->exif, $result); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getData - */ - public function testGetData() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Exif', 'data'); - $reflProperty->setAccessible(true); - - $this->assertEquals($reflProperty->getValue($this->exif), $this->exif->getData()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::setData - */ - public function testSetData() - { - $testData = array('foo', 'bar', 'baz'); - $reflProperty = new \ReflectionProperty('\PHPExif\Exif', 'data'); - $reflProperty->setAccessible(true); - - $result = $this->exif->setData($testData); - - $this->assertEquals($testData, $reflProperty->getValue($this->exif)); - $this->assertEquals($this->exif, $result); - } - - /** - * - * @dataProvider providerUndefinedPropertiesReturnFalse - * @covers \PHPExif\Exif::getAperture - * @covers \PHPExif\Exif::getIso - * @covers \PHPExif\Exif::getExposure - * @covers \PHPExif\Exif::getExposureMilliseconds - * @covers \PHPExif\Exif::getFocusDistance - * @covers \PHPExif\Exif::getWidth - * @covers \PHPExif\Exif::getHeight - * @covers \PHPExif\Exif::getTitle - * @covers \PHPExif\Exif::getCaption - * @covers \PHPExif\Exif::getCopyright - * @covers \PHPExif\Exif::getKeywords - * @covers \PHPExif\Exif::getCamera - * @covers \PHPExif\Exif::getHorizontalResolution - * @covers \PHPExif\Exif::getVerticalResolution - * @covers \PHPExif\Exif::getSoftware - * @covers \PHPExif\Exif::getFocalLength - * @covers \PHPExif\Exif::getCreationDate - * @covers \PHPExif\Exif::getAuthor - * @covers \PHPExif\Exif::getCredit - * @covers \PHPExif\Exif::getSource - * @covers \PHPExif\Exif::getJobtitle - * @covers \PHPExif\Exif::getMimeType - * @covers \PHPExif\Exif::getFileSize - * @covers \PHPExif\Exif::getHeadline - * @covers \PHPExif\Exif::getColorSpace - * @covers \PHPExif\Exif::getOrientation - * @covers \PHPExif\Exif::getGPS - * @param string $accessor - */ - public function testUndefinedPropertiesReturnFalse($accessor) - { - $expected = false; - $this->assertEquals($expected, $this->exif->$accessor()); - } - - /** - * Data provider for testUndefinedPropertiesReturnFalse - * - * @return array - */ - public function providerUndefinedPropertiesReturnFalse() - { - return array( - array('getAperture'), - array('getIso'), - array('getExposure'), - array('getExposureMilliseconds'), - array('getFocusDistance'), - array('getWidth'), - array('getHeight'), - array('getTitle'), - array('getCaption'), - array('getCopyright'), - array('getKeywords'), - array('getCamera'), - array('getHorizontalResolution'), - array('getVerticalResolution'), - array('getSoftware'), - array('getFocalLength'), - array('getCreationDate'), - array('getAuthor'), - array('getHeadline'), - array('getCredit'), - array('getSource'), - array('getJobtitle'), - array('getMimeType'), - array('getFileSize'), - array('getHeadline'), - array('getColorSpace'), - array('getOrientation'), - array('getGPS'), - ); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getAperture - */ - public function testGetAperture() - { - $expected = 'f/8.0'; - $data[\PHPExif\Exif::APERTURE] = $expected; - $this->exif->setData($data); - - $this->assertEquals($expected, $this->exif->getAperture()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getIso - */ - public function testGetIso() - { - $expected = 200; - $data[\PHPExif\Exif::ISO] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getIso()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getExposure - */ - public function testGetExposure() - { - $expected = '1/320'; - $data[\PHPExif\Exif::EXPOSURE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getExposure()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getExposureMilliseconds - */ - public function testGetExposureMilliseconds() - { - $rawData = array( - array(1/300, '1/300'), - array(0.0025, 0.0025), - ); - - foreach ($rawData as $data) { - $expected = reset($data); - $value = end($data); - - $data[\PHPExif\Exif::EXPOSURE] = $value; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getExposureMilliseconds()); - } - } - - /** - * @group exif - * @covers \PHPExif\Exif::getFocusDistance - */ - public function testGetFocusDistance() - { - $expected = '7.94m'; - $data[\PHPExif\Exif::FOCAL_DISTANCE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getFocusDistance()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getWidth - */ - public function testGetWidth() - { - $expected = 500; - $data[\PHPExif\Exif::WIDTH] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getWidth()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getHeight - */ - public function testGetHeight() - { - $expected = 332; - $data[\PHPExif\Exif::HEIGHT] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getHeight()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getTitle - */ - public function testGetTitle() - { - $expected = 'Morning Glory Pool'; - $data[\PHPExif\Exif::TITLE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getTitle()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getCaption - */ - public function testGetCaption() - { - $expected = 'Foo Bar Baz'; - $data[\PHPExif\Exif::CAPTION] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getCaption()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getCopyright - */ - public function testGetCopyright() - { - $expected = 'Miljar'; - $data[\PHPExif\Exif::COPYRIGHT] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getCopyright()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getKeywords - */ - public function testGetKeywords() - { - $expected = array('18-200', 'D90', 'USA', 'Wyoming', 'Yellowstone'); - $data[\PHPExif\Exif::KEYWORDS] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getKeywords()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getCamera - */ - public function testGetCamera() - { - $expected = 'NIKON D90'; - $data[\PHPExif\Exif::CAMERA] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getCamera()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getHorizontalResolution - */ - public function testGetHorizontalResolution() - { - $expected = 240; - $data[\PHPExif\Exif::HORIZONTAL_RESOLUTION] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getHorizontalResolution()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getVerticalResolution - */ - public function testGetVerticalResolution() - { - $expected = 240; - $data[\PHPExif\Exif::VERTICAL_RESOLUTION] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getVerticalResolution()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getSoftware - */ - public function testGetSoftware() - { - $expected = 'Adobe Photoshop Lightroom'; - $data[\PHPExif\Exif::SOFTWARE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getSoftware()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getFocalLength - */ - public function testGetFocalLength() - { - $expected = 18; - $data[\PHPExif\Exif::FOCAL_LENGTH] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getFocalLength()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getCreationDate - */ - public function testGetCreationDate() - { - $expected = '2011-06-07 20:01:50'; - $input = \DateTime::createFromFormat('Y-m-d H:i:s', $expected); - $data[\PHPExif\Exif::CREATION_DATE] = $input; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getCreationDate()->format('Y-m-d H:i:s')); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getAuthor - */ - public function testGetAuthor() - { - $expected = 'John Smith'; - $data[\PHPExif\Exif::AUTHOR] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getAuthor()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getHeadline - */ - public function testGetHeadline() - { - $expected = 'Foobar Baz'; - $data[\PHPExif\Exif::HEADLINE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getHeadline()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getCredit - */ - public function testGetCredit() - { - $expected = 'john.smith@example.com'; - $data[\PHPExif\Exif::CREDIT] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getCredit()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getSource - */ - public function testGetSource() - { - $expected = 'FBB NEWS'; - $data[\PHPExif\Exif::SOURCE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getSource()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getJobtitle - */ - public function testGetJobtitle() - { - $expected = 'Yellowstone\'s geysers and pools'; - $data[\PHPExif\Exif::JOB_TITLE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getJobtitle()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getColorSpace - */ - public function testGetColorSpace() - { - $expected = 'RGB'; - $data[\PHPExif\Exif::COLORSPACE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getColorSpace()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getMimeType - */ - public function testGetMimeType() - { - $expected = 'image/jpeg'; - $data[\PHPExif\Exif::MIMETYPE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getMimeType()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getFileSize - */ - public function testGetFileSize() - { - $expected = '27852365'; - $data[\PHPExif\Exif::FILESIZE] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getFileSize()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getOrientation - */ - public function testGetOrientation() - { - $expected = 1; - $data[\PHPExif\Exif::ORIENTATION] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getOrientation()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::getGPS - */ - public function testGetGPS() - { - $expected = '40.333452380556,-20.167314813889'; - $data[\PHPExif\Exif::GPS] = $expected; - $this->exif->setData($data); - $this->assertEquals($expected, $this->exif->getGPS()); - } - - /** - * @group exif - * @covers \PHPExif\Exif::setAperture - * @covers \PHPExif\Exif::setIso - * @covers \PHPExif\Exif::setExposure - * @covers \PHPExif\Exif::setFocusDistance - * @covers \PHPExif\Exif::setWidth - * @covers \PHPExif\Exif::setHeight - * @covers \PHPExif\Exif::setTitle - * @covers \PHPExif\Exif::setCaption - * @covers \PHPExif\Exif::setCopyright - * @covers \PHPExif\Exif::setKeywords - * @covers \PHPExif\Exif::setCamera - * @covers \PHPExif\Exif::setHorizontalResolution - * @covers \PHPExif\Exif::setVerticalResolution - * @covers \PHPExif\Exif::setSoftware - * @covers \PHPExif\Exif::setFocalLength - * @covers \PHPExif\Exif::setCreationDate - * @covers \PHPExif\Exif::setAuthor - * @covers \PHPExif\Exif::setCredit - * @covers \PHPExif\Exif::setSource - * @covers \PHPExif\Exif::setJobtitle - * @covers \PHPExif\Exif::setMimeType - * @covers \PHPExif\Exif::setFileSize - * @covers \PHPExif\Exif::setHeadline - * @covers \PHPExif\Exif::setColorSpace - * @covers \PHPExif\Exif::setOrientation - * @covers \PHPExif\Exif::setGPS - */ - public function testMutatorMethodsSetInProperty() - { - $reflClass = new \ReflectionClass(get_class($this->exif)); - $constants = $reflClass->getConstants(); - - $reflProp = new \ReflectionProperty(get_class($this->exif), 'data'); - $reflProp->setAccessible(true); - - $expected = 'foo'; - foreach ($constants as $name => $value) { - $setter = 'set' . ucfirst($value); - - switch ($value) { - case 'creationdate': - $now = new \DateTime(); - $this->exif->$setter($now); - $propertyValue = $reflProp->getValue($this->exif); - $this->assertSame($now, $propertyValue[$value]); - break; - case 'gps': - $coords = '40.333452380556,-20.167314813889'; - $setter = 'setGPS'; - $this->exif->$setter($coords); - $propertyValue = $reflProp->getValue($this->exif); - $this->assertEquals($coords, $propertyValue[$value]); - break; - case 'focalDistance': - $setter = 'setFocusDistance'; - default: - $this->exif->$setter($expected); - $propertyValue = $reflProp->getValue($this->exif); - $this->assertEquals($expected, $propertyValue[$value]); - break; - } - } - } - - /** - * Test that the values returned by both adapters are equal - * - * @group consistency - * @covers \PHPExif\Exif::getAperture - * @covers \PHPExif\Exif::getIso - * @covers \PHPExif\Exif::getExposure - * @covers \PHPExif\Exif::getExposureMilliseconds - * @covers \PHPExif\Exif::getFocusDistance - * @covers \PHPExif\Exif::getWidth - * @covers \PHPExif\Exif::getHeight - * @covers \PHPExif\Exif::getTitle - * @covers \PHPExif\Exif::getCaption - * @covers \PHPExif\Exif::getCopyright - * @covers \PHPExif\Exif::getKeywords - * @covers \PHPExif\Exif::getCamera - * @covers \PHPExif\Exif::getHorizontalResolution - * @covers \PHPExif\Exif::getVerticalResolution - * @covers \PHPExif\Exif::getSoftware - * @covers \PHPExif\Exif::getFocalLength - * @covers \PHPExif\Exif::getCreationDate - * @covers \PHPExif\Exif::getAuthor - * @covers \PHPExif\Exif::getCredit - * @covers \PHPExif\Exif::getSource - * @covers \PHPExif\Exif::getJobtitle - * @covers \PHPExif\Exif::getMimeType - * @covers \PHPExif\Exif::getFileSize - */ - public function testAdapterConsistency() - { - $reflClass = new \ReflectionClass('\PHPExif\Exif'); - $methods = $reflClass->getMethods(ReflectionMethod::IS_PUBLIC); - $testfiles = array( - PHPEXIF_TEST_ROOT . '/files/morning_glory_pool_500.jpg', - PHPEXIF_TEST_ROOT . '/files/dsc_5794.jpg' - ); - - $adapter_exiftool = new \PHPExif\Adapter\Exiftool(); - $adapter_native = new \PHPExif\Adapter\Native(); - - foreach ($testfiles as $file) { - $result_exiftool = $adapter_exiftool->getExifFromFile($file); - $result_native = $adapter_native->getExifFromFile($file); - - // find all Getter methods on the results and compare its output - foreach ($methods as $method) { - $name = $method->getName(); - if (strpos($name, 'get') !== 0 || $name == 'getRawData' || $name == 'getData') { - continue; - } - $this->assertEquals( - call_user_func(array($result_native, $name)), - call_user_func(array($result_exiftool, $name)), - 'Adapter difference detected in method "' . $name . '" on image "' . basename($file) . '"' - ); - } - } - } -} - diff --git a/tests/PHPExif/Hydrator/MutatorTest.php b/tests/PHPExif/Hydrator/MutatorTest.php deleted file mode 100644 index 280188b..0000000 --- a/tests/PHPExif/Hydrator/MutatorTest.php +++ /dev/null @@ -1,69 +0,0 @@ - - * @covers \PHPExif\Hydrator\HydratorInterface - */ -class MutatorTest extends \PHPUnit_Framework_TestCase -{ - /** - * Setup function before the tests - */ - public function setUp() - { - } - - /** - * @group hydrator - * @covers \PHPExif\Hydrator\Mutator::hydrate - */ - public function testHydrateCallsDetermineMutator() - { - // input data - $input = array( - 'foo' => 'bar', - ); - - // create mock - $mock = $this->getMock('\\PHPExif\\Hydrator\\Mutator', array('determineMutator')); - - $mock->expects($this->exactly(count($input))) - ->method('determineMutator') - ->will($this->returnValue('setFoo')); - - $object = new TestClass(); - - // do the test - $mock->hydrate($object, $input); - } - - /** - * @group hydrator - * @covers \PHPExif\Hydrator\Mutator::hydrate - */ - public function testHydrateCallsMutatorsOnObject() - { - // input data - $input = array( - 'bar' => 'baz', - ); - - // create mock - $mock = $this->getMock('TestClass', array('setBar')); - - $mock->expects($this->once()) - ->method('setBar') - ->with($this->equalTo($input['bar'])); - - // do the test - $hydrator = new \PHPExif\Hydrator\Mutator; - $hydrator->hydrate($mock, $input); - } -} - -class TestClass -{ - public function setBar() - { - } -} - diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php deleted file mode 100644 index 09d2456..0000000 --- a/tests/PHPExif/Mapper/ExiftoolMapperTest.php +++ /dev/null @@ -1,296 +0,0 @@ - - */ -class ExiftoolMapperTest extends \PHPUnit_Framework_TestCase -{ - protected $mapper; - - public function setUp() - { - $this->mapper = new \PHPExif\Mapper\Exiftool; - } - - /** - * @group mapper - */ - public function testClassImplementsCorrectInterface() - { - $this->assertInstanceOf('\\PHPExif\\Mapper\\MapperInterface', $this->mapper); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataIgnoresFieldIfItDoesntExist() - { - $rawData = array('foo' => 'bar'); - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertCount(0, $mapped); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataMapsFieldsCorrectly() - { - $reflProp = new \ReflectionProperty(get_class($this->mapper), 'map'); - $reflProp->setAccessible(true); - $map = $reflProp->getValue($this->mapper); - - // ignore custom formatted data stuff: - unset($map[\PHPExif\Mapper\Exiftool::APERTURE]); - unset($map[\PHPExif\Mapper\Exiftool::APPROXIMATEFOCUSDISTANCE]); - unset($map[\PHPExif\Mapper\Exiftool::DATETIMEORIGINAL]); - unset($map[\PHPExif\Mapper\Exiftool::EXPOSURETIME]); - unset($map[\PHPExif\Mapper\Exiftool::FOCALLENGTH]); - unset($map[\PHPExif\Mapper\Exiftool::GPSLATITUDE]); - unset($map[\PHPExif\Mapper\Exiftool::GPSLONGITUDE]); - - // create raw data - $keys = array_keys($map); - $values = array(); - $values = array_pad($values, count($keys), 'foo'); - $rawData = array_combine($keys, $values); - - - $mapped = $this->mapper->mapRawData($rawData); - - $i = 0; - foreach ($mapped as $key => $value) { - $this->assertEquals($map[$keys[$i]], $key); - $i++; - } - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyFormatsAperture() - { - $rawData = array( - \PHPExif\Mapper\Exiftool::APERTURE => 0.123, - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals('f/0.1', reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyFormatsFocusDistance() - { - $rawData = array( - \PHPExif\Mapper\Exiftool::APPROXIMATEFOCUSDISTANCE => 50, - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals('50m', reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyFormatsCreationDate() - { - $rawData = array( - \PHPExif\Mapper\Exiftool::DATETIMEORIGINAL => '2015:04:01 12:11:09', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $result = reset($mapped); - $this->assertInstanceOf('\\DateTime', $result); - $this->assertEquals( - reset($rawData), - $result->format('Y:m:d H:i:s') - ); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyIgnoresIncorrectCreationDate() - { - $rawData = array( - \PHPExif\Mapper\Exiftool::DATETIMEORIGINAL => '2015:04:01', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals(false, reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyFormatsExposureTime() - { - $rawData = array( - '1/30' => 10/300, - '1/400' => 2/800, - '1/400' => 1/400, - '0' => 0, - ); - - foreach ($rawData as $expected => $value) { - $mapped = $this->mapper->mapRawData(array( - \PHPExif\Mapper\Exiftool::EXPOSURETIME => $value, - )); - - $this->assertEquals($expected, reset($mapped)); - } - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyFormatsFocalLength() - { - $rawData = array( - \PHPExif\Mapper\Exiftool::FOCALLENGTH => '15 m', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals(15, reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyFormatsGPSData() - { - $this->mapper->setNumeric(false); - $result = $this->mapper->mapRawData( - array( - \PHPExif\Mapper\Exiftool::GPSLATITUDE => '40 deg 20\' 0.42857" N', - 'GPS:GPSLatitudeRef' => 'North', - \PHPExif\Mapper\Exiftool::GPSLONGITUDE => '20 deg 10\' 2.33333" W', - 'GPS:GPSLongitudeRef' => 'West', - ) - ); - - $expected = '40.333452380556,-20.167314813889'; - $this->assertCount(1, $result); - $this->assertEquals($expected, reset($result)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyFormatsNumericGPSData() - { - $result = $this->mapper->mapRawData( - array( - \PHPExif\Mapper\Exiftool::GPSLATITUDE => '40.333452381', - 'GPS:GPSLatitudeRef' => 'North', - \PHPExif\Mapper\Exiftool::GPSLONGITUDE => '20.167314814', - 'GPS:GPSLongitudeRef' => 'West', - ) - ); - - $expected = '40.333452381,-20.167314814'; - $this->assertCount(1, $result); - $this->assertEquals($expected, reset($result)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyIgnoresIncorrectGPSData() - { - $this->mapper->setNumeric(false); - $result = $this->mapper->mapRawData( - array( - \PHPExif\Mapper\Exiftool::GPSLATITUDE => '40.333452381', - 'GPS:GPSLatitudeRef' => 'North', - \PHPExif\Mapper\Exiftool::GPSLONGITUDE => '20.167314814', - 'GPS:GPSLongitudeRef' => 'West', - ) - ); - - $this->assertCount(0, $result); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::mapRawData - */ - public function testMapRawDataCorrectlyIgnoresIncompleteGPSData() - { - $result = $this->mapper->mapRawData( - array( - \PHPExif\Mapper\Exiftool::GPSLATITUDE => '40.333452381', - 'GPS:GPSLatitudeRef' => 'North', - ) - ); - - $this->assertCount(0, $result); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Exiftool::setNumeric - */ - public function testSetNumericInProperty() - { - $reflProperty = new \ReflectionProperty(get_class($this->mapper), 'numeric'); - $reflProperty->setAccessible(true); - - $expected = true; - $this->mapper->setNumeric($expected); - - $this->assertEquals($expected, $reflProperty->getValue($this->mapper)); - } - - public function testMapRawDataCorrectlyFormatsDifferentDateTimeString() - { - $rawData = array( - \PHPExif\Mapper\Exiftool::DATETIMEORIGINAL => '2014-12-15 00:12:00' - ); - - $mapped = $this->mapper->mapRawData( - $rawData - ); - - $result = reset($mapped); - $this->assertInstanceOf('\DateTime', $result); - $this->assertEquals( - reset($rawData), - $result->format("Y-m-d H:i:s") - ); - } - - public function testMapRawDataCorrectlyIgnoresInvalidCreateDate() - { - $rawData = array( - \PHPExif\Mapper\Exiftool::DATETIMEORIGINAL => 'Invalid Date String' - ); - - $result = $this->mapper->mapRawData( - $rawData - ); - - $this->assertCount(0, $result); - $this->assertNotEquals( - reset($rawData), - $result - ); - } -} diff --git a/tests/PHPExif/Mapper/NativeMapperTest.php b/tests/PHPExif/Mapper/NativeMapperTest.php deleted file mode 100644 index a18bea4..0000000 --- a/tests/PHPExif/Mapper/NativeMapperTest.php +++ /dev/null @@ -1,284 +0,0 @@ - - */ -class NativeMapperTest extends \PHPUnit_Framework_TestCase -{ - protected $mapper; - - public function setUp() - { - $this->mapper = new \PHPExif\Mapper\Native; - } - - /** - * @group mapper - */ - public function testClassImplementsCorrectInterface() - { - $this->assertInstanceOf('\\PHPExif\\Mapper\\MapperInterface', $this->mapper); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataIgnoresFieldIfItDoesntExist() - { - $rawData = array('foo' => 'bar'); - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertCount(0, $mapped); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataMapsFieldsCorrectly() - { - $reflProp = new \ReflectionProperty(get_class($this->mapper), 'map'); - $reflProp->setAccessible(true); - $map = $reflProp->getValue($this->mapper); - - // ignore custom formatted data stuff: - unset($map[\PHPExif\Mapper\Native::DATETIMEORIGINAL]); - unset($map[\PHPExif\Mapper\Native::EXPOSURETIME]); - unset($map[\PHPExif\Mapper\Native::FOCALLENGTH]); - unset($map[\PHPExif\Mapper\Native::XRESOLUTION]); - unset($map[\PHPExif\Mapper\Native::YRESOLUTION]); - unset($map[\PHPExif\Mapper\Native::GPSLATITUDE]); - unset($map[\PHPExif\Mapper\Native::GPSLONGITUDE]); - - // create raw data - $keys = array_keys($map); - $values = array(); - $values = array_pad($values, count($keys), 'foo'); - $rawData = array_combine($keys, $values); - - - $mapped = $this->mapper->mapRawData($rawData); - - $i = 0; - foreach ($mapped as $key => $value) { - $this->assertEquals($map[$keys[$i]], $key); - $i++; - } - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataCorrectlyFormatsDateTimeOriginal() - { - $rawData = array( - \PHPExif\Mapper\Native::DATETIMEORIGINAL => '2015:04:01 12:11:09', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $result = reset($mapped); - $this->assertInstanceOf('\\DateTime', $result); - $this->assertEquals( - reset($rawData), - $result->format('Y:m:d H:i:s') - ); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataCorrectlyIgnoresIncorrectDateTimeOriginal() - { - $rawData = array( - \PHPExif\Mapper\Native::DATETIMEORIGINAL => '2015:04:01', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals(false, reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataCorrectlyFormatsExposureTime() - { - $rawData = array( - '1/30' => 10/300, - '1/400' => 2/800, - '1/400' => 1/400, - '0' => 0, - ); - - foreach ($rawData as $expected => $value) { - $mapped = $this->mapper->mapRawData(array( - \PHPExif\Mapper\Native::EXPOSURETIME => $value, - )); - - $this->assertEquals($expected, reset($mapped)); - } - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataCorrectlyFormatsFocalLength() - { - $rawData = array( - \PHPExif\Mapper\Native::FOCALLENGTH => '30/5', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals(6, reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataCorrectlyFormatsXResolution() - { - $rawData = array( - \PHPExif\Mapper\Native::XRESOLUTION => '1500/300', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals(1500, reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataCorrectlyFormatsYResolution() - { - $rawData = array( - \PHPExif\Mapper\Native::YRESOLUTION => '1500/300', - ); - - $mapped = $this->mapper->mapRawData($rawData); - - $this->assertEquals(1500, reset($mapped)); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataFlattensRawDataWithSections() - { - $rawData = array( - \PHPExif\Mapper\Native::SECTION_COMPUTED => array( - \PHPExif\Mapper\Native::TITLE => 'Hello', - ), - \PHPExif\Mapper\Native::HEADLINE => 'Headline', - ); - $mapped = $this->mapper->mapRawData($rawData); - $this->assertCount(2, $mapped); - $keys = array_keys($mapped); - - $expected = array( - \PHPExif\Mapper\Native::TITLE, - \PHPExif\Mapper\Native::HEADLINE - ); - $this->assertEquals($expected, $keys); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::mapRawData - */ - public function testMapRawDataCorrectlyFormatsGPSData() - { - $expected = array( - '40.333452380952,-20.167314814815' => array( - 'GPSLatitude' => array('40/1', '20/1', '15/35'), - 'GPSLatitudeRef' => 'N', - 'GPSLongitude' => array('20/1', '10/1', '35/15'), - 'GPSLongitudeRef' => 'W', - ), - '0,-0' => array( - 'GPSLatitude' => array('0/0', '0/0', '0/0'), - 'GPSLatitudeRef' => 'N', - 'GPSLongitude' => array('0/0', '0/0', '0/0'), - 'GPSLongitudeRef' => 'W', - ), - '71.706936,-42.604303' => array( - 'GPSLatitude' => array('71.706936'), - 'GPSLatitudeRef' => 'N', - 'GPSLongitude' => array('42.604303'), - 'GPSLongitudeRef' => 'W', - ), - ); - - foreach ($expected as $key => $value) { - $result = $this->mapper->mapRawData($value); - $this->assertEquals($key, reset($result)); - } - } - - public function testMapRawDataCorrectlyFormatsDifferentDateTimeString() - { - $rawData = array( - \PHPExif\Mapper\Native::DATETIMEORIGINAL => '2014-12-15 00:12:00' - ); - - $mapped = $this->mapper->mapRawData( - $rawData - ); - - $result = reset($mapped); - $this->assertInstanceOf('\DateTime', $result); - $this->assertEquals( - reset($rawData), - $result->format("Y-m-d H:i:s") - ); - } - - public function testMapRawDataCorrectlyIgnoresInvalidCreateDate() - { - $rawData = array( - \PHPExif\Mapper\Native::DATETIMEORIGINAL => 'Invalid Date String' - ); - - $result = $this->mapper->mapRawData( - $rawData - ); - - $this->assertCount(0, $result); - $this->assertNotEquals( - reset($rawData), - $result - ); - } - - /** - * @group mapper - * @covers \PHPExif\Mapper\Native::normalizeComponent - */ - public function testNormalizeComponentCorrectly() - { - $reflMethod = new \ReflectionMethod('\PHPExif\Mapper\Native', 'normalizeComponent'); - $reflMethod->setAccessible(true); - - $rawData = array( - '2/800' => 0.0025, - '1/400' => 0.0025, - '0/1' => 0, - '0' => 0, - ); - - foreach ($rawData as $value => $expected) { - $normalized = $reflMethod->invoke($this->mapper, $value); - - $this->assertEquals($expected, $normalized); - } - } -} diff --git a/tests/PHPExif/Reader/ReaderTest.php b/tests/PHPExif/Reader/ReaderTest.php deleted file mode 100644 index 82aa133..0000000 --- a/tests/PHPExif/Reader/ReaderTest.php +++ /dev/null @@ -1,161 +0,0 @@ - - * @covers \PHPExif\Reader\ReaderInterface - * @covers \PHPExif\Adapter\NoAdapterException - */ -class ReaderTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \PHPExif\Reader\Reader - */ - protected $reader; - - /** - * Setup function before the tests - */ - public function setUp() - { - $adapter = $this->getMock('\PHPExif\Adapter\AdapterInterface'); - $this->reader = new \PHPExif\Reader\Reader($adapter); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::__construct - */ - public function testConstructorWithAdapter() - { - $mock = $this->getMock('\PHPExif\Adapter\AdapterInterface'); - $reflProperty = new \ReflectionProperty('\PHPExif\Reader\Reader', 'adapter'); - $reflProperty->setAccessible(true); - - $reader = new \PHPExif\Reader\Reader($mock); - - $this->assertSame($mock, $reflProperty->getValue($reader)); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::getAdapter - */ - public function testGetAdapterFromProperty() - { - $mock = $this->getMock('\PHPExif\Adapter\AdapterInterface'); - - $reflProperty = new \ReflectionProperty('\PHPExif\Reader\Reader', 'adapter'); - $reflProperty->setAccessible(true); - $reflProperty->setValue($this->reader, $mock); - - $this->assertSame($mock, $this->reader->getAdapter()); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::getAdapter - * @covers \PHPExif\Adapter\NoAdapterException - * @expectedException \PHPExif\Adapter\NoAdapterException - */ - public function testGetAdapterThrowsExceptionWhenNoAdapterIsSet() - { - $reflProperty = new \ReflectionProperty('\PHPExif\Reader\Reader', 'adapter'); - $reflProperty->setAccessible(true); - $reflProperty->setValue($this->reader, null); - - $this->reader->getAdapter(); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::read - */ - public function testGetExifPassedToAdapter() - { - $adapter = $this->getMock('\PHPExif\Adapter\AdapterInterface'); - $adapter->expects($this->once())->method('getExifFromFile'); - - $reflProperty = new \ReflectionProperty('\PHPExif\Reader\Reader', 'adapter'); - $reflProperty->setAccessible(true); - $reflProperty->setValue($this->reader, $adapter); - - $this->reader->read('/tmp/foo.bar'); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::factory - * @expectedException InvalidArgumentException - */ - public function testFactoryThrowsException() - { - \PHPExif\Reader\Reader::factory('foo'); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::factory - */ - public function testFactoryReturnsCorrectType() - { - $reader = \PHPExif\Reader\Reader::factory(\PHPExif\Reader\Reader::TYPE_NATIVE); - - $this->assertInstanceOf('\PHPExif\Reader\Reader', $reader); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::factory - */ - public function testFactoryAdapterTypeNative() - { - $reader = \PHPExif\Reader\Reader::factory(\PHPExif\Reader\Reader::TYPE_NATIVE); - $reflProperty = new \ReflectionProperty('\PHPExif\Reader\Reader', 'adapter'); - $reflProperty->setAccessible(true); - - $adapter = $reflProperty->getValue($reader); - - $this->assertInstanceOf('\PHPExif\Adapter\Native', $adapter); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::factory - */ - public function testFactoryAdapterTypeExiftool() - { - $reader = \PHPExif\Reader\Reader::factory(\PHPExif\Reader\Reader::TYPE_EXIFTOOL); - $reflProperty = new \ReflectionProperty('\PHPExif\Reader\Reader', 'adapter'); - $reflProperty->setAccessible(true); - - $adapter = $reflProperty->getValue($reader); - - $this->assertInstanceOf('\PHPExif\Adapter\Exiftool', $adapter); - } - - /** - * @group reader - * @covers \PHPExif\Reader\Reader::getExifFromFile - */ - public function testGetExifFromFileCallsReadMethod() - { - $mock = $this->getMock( - '\\PHPExif\\Reader\\Reader', - array('read'), - array(), - '', - false - ); - - $expected = '/foo/bar/baz'; - $expectedResult = 'test'; - - $mock->expects($this->once()) - ->method('read') - ->with($this->equalTo($expected)) - ->will($this->returnValue($expectedResult)); - - $result = $mock->getExifFromFile($expected); - $this->assertEquals($expectedResult, $result); - } -} - diff --git a/tests/PHPExif/ReaderTest.php b/tests/PHPExif/ReaderTest.php new file mode 100644 index 0000000..450ed67 --- /dev/null +++ b/tests/PHPExif/ReaderTest.php @@ -0,0 +1,56 @@ + + */ +class ReaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @group reader + * @covers \PHPExif\Reader::__construct + */ + public function testConstructorCallsSetData() + { + $mock = $this->getMockBuilder('\\PHPExif\\Reader') + ->disableOriginalConstructor() + ->getMock(); + $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') + ->getMock(); + + // now call the constructor + $reflectedClass = new ReflectionClass('\\PHPExif\\Reader'); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($mock, array($adapter)); + + // verify if set in property + $reflProperty = new \ReflectionProperty('\\PHPExif\\Reader', 'adapter'); + $reflProperty->setAccessible(true); + + $actual = $reflProperty->getValue($mock); + + $this->assertSame( + $adapter, + $actual + ); + } + + /** + * @group reader + * @covers \PHPExif\Reader::getAdapter + */ + public function testGetAdapterReturnsFromProperty() + { + $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') + ->getMock(); + $reader = new \PHPExif\Reader($adapter); + + $reflProperty = new \ReflectionProperty('\\PHPExif\\Reader', 'adapter'); + $reflProperty->setAccessible(true); + + $relfProperty->setValue($reader, $adapter); + + $this->assertSame( + $adapter, + $reader->getAdapter() + ); + } +} diff --git a/tests/files/dsc_5794.jpg b/tests/files/dsc_5794.jpg deleted file mode 100644 index 6a2345160369a380ce610fc155200280d768efe7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 229970 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\h!Gat!<8Y!)Z1j-V` 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 Br49f9 diff --git a/tests/files/empty.jpg b/tests/files/empty.jpg deleted file mode 100644 index 5481894..0000000 --- a/tests/files/empty.jpg +++ /dev/null @@ -1 +0,0 @@ -fmqjsdfmjqsdmfkj diff --git a/tests/files/morning_glory_pool_500.jpg b/tests/files/morning_glory_pool_500.jpg deleted file mode 100644 index aa037c74ca90c0d705550b4164cae600cf7aebd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 266269 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 z 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 z zKh=KUF=1KZ_c>+iwsJ}P-))qks+$p{Udu3-cSpw6a-xx8R(Zi!hkHt2wCR%7d|S-2 zWGO!XzYc#7|3JuTQL{O}>krHe{T+N@iu;?1@V$#-2d>+t<_68)e z5pv&%bF;D2J0=-o#S<(!5CUGLQzTKkvD8Fbhz~}oY~7AB!qIRaOl^@3G;AB>}YhRHgPQ6OFtiKhZH0UO? zEHMXb*`%pNR%dI49Bg?nA(I)Rjz%S0QB70}PipR6Dws+MeJ98Y)}J*EW*0b+8R14~ zjLsP9P^?Q3UX9YXQLz`knj?R|HU5F^eP;S|nQxVH-ch$gn$WEv-9}Hfe5ww$9z4vO z^T{k;)VchchwQ-&TF@ExbW;sdrO~g=*gLBE>vhYy{RRDDpi!~1Xml6JA2%|s}(C`at$i)15X@n%YGXPuU+-- zMY7M2xQa&GwHH<-mD4Kp;)yVWD;{LVlLkkCP6HdFbu;K16cxHVh9QcLx7>h7%Y~pzW0D&;(9kKk=xp_q^3RmLgkQ*oShF;db`mTwPOq>XM@gKtcm_8OHm_^4>6 ziXT^%;|vqH?S!4{IqR$~XXT%Dlr2a6umU%I zpHM7g7e$D~vPF>QNSa1Z;TMcukxi|Nsn7{BBH2wkM~HgdVQ#lN{-++)OP5d|+=g3`cNWK`hQYoy3 z0ESa!dAz7}f_T%slD0aBaIrwz7ToLkO_H>vo`rTJPVMHd2lY9=FB(;@CtkLfA=Tfz zUHrRi{+!eVWa9?4t&Hs3q_%r|oOyby&w3852>T)nSsUJPT6}!BiF_$wG0Bj-?yaE( zl^#+pK+?!#(WgqC?D3b##fhC$B$Xh8Bg-1Ba>RxqtgDBkZ>d?BGPacf5qb}oUzgK>|a=k89!#S$>FCM+6OJjd$3wklLxjoDc2fC1E=&LoST~z}m?XnB6H{kU} z0LG&AblNYLmaR}UiqN&Fk&67ysZ&~6kySvqq;0~0!0}Fe8FErgVn&pJ<{%r&qP2k~ zDsIhcODU@*YPi@V^xKv3ja-ft{ptYCK0%L5kZ4%VtGTz8!+2h5IW3MS#d3JQwt8vT z*KWprn|IAoa^!Lf&4Pweu(78j1>64sItbq;SoV$Cnms;rRq5aZTC@eucALt_*Wg%(@D3J(9gux3wQX+2bX1F z=4zw(Tux)lkc5s>v$ZC^g-fIDw&kFTM0OTXpIR1!4;pEQiK8(BOR03L1$HDWuvNX> z6bibH0&H-P#mk(>BE|+OGDoDABT^{0MbzYMrDP1{eA`hM#(d_y3zKAWGO@+^u2xn> zjBPs2U5+wU>rl(q&`4^Ic4h{pDz_`!tZ+=Kh@i2RE@aMBP8=^W=4%g)ixyT#;k7Yk zLIAxbLog1AZpi?rkQ!F`uVc!vo*hL z`iY?3t6OTx#Jeqy647M`ameLa@2^_@mzDZ-wcF=W zgqAubAAnHh%?JY-UQZ1cN7NCVY{uv*T~Z-n^&w`VdJActW?Xz$wa8>mZz8D<>V}vK zwqV6k)EMqHRqd!t>Q~ilAEnuxAL;i7$JY9f^~-9$0`1kxdhONXp|w!A9f!*_`0Ic9 zR4bWUr)752PgQS0)Qa`}#`*)FNO7^%qKY@1v`)SYG>W04Eh4*$NepjgSy<~sU?5%n z<(Vx$LzZVqipY#50UKuuju6|&tu|zI1sqnXHEj6fe^NO*axT@sPbX_jnJ(_`=N>Im zr?H(^Mwo@io$Uu%JbJ@#-eT*jN#A(aLRo#}6$vY>l17sFNsxg=lOU3t%sy9b#;0Np zCgnnkH^U^#QLZ*=AZH~aa)(aDd67*WDgm<87S7{O4(;8#E#e$bu09<)mOLAj>h|6u zf6iE};D_}U+7$ckL{F0(XlRMoz~ zsP!n)yb%Wz0=uQnOBhWSONz>-C33WlmCI-GqB3K;8PpXLRI)PxyG9h&k>v}h3%j#N zgYbE*LOFEg#_Iv5F^>i%QcVXhxMtk76I3>$I0)7HGmUHNH&m-~I`%W@yI{Fpz)K?M zGpjXd(9_J(D~k-x5v^sltSp*fD!Y2GvhrP`8e-)${wwis2Ztg?QC>!>cVNs}L9*#U zYIPtGMUtSY2b$wNZwHCuqQ8lzH8-FkO)5wuL)ki4=29#TL=wNLO2y?LNHux?06yA7 zDE%$Ve<9e+Q>xOuo>A@&5?V_pQ$ekqk1c`Y7cbj2R2Iw_1AyGkHe7g_B_*l(dIKyZ z+W3zC7?1<=78W(?XV5E402r$;g%(yBX#7OZZ{W%Xli{lPjEr|=P;{L-Q462tB&hlQ z#i1ON>INRhch?nHwW8|UHaTYoM<3;y+&1)PArk0hmcSVZumJ;CX2wuDhPdUHf`H*szVUP&8ziP zJC)l{8%t~Hw-@?(&-lFMDzy+BS$DDd9>92R0l4$IRlVIDq|*LVPl(v}mu2*8&%8CY zg2I}{ya&@rj(07IIetz-!p22}F_JfQXqZ-}2eYVG8!;iY*gODJ12nd7J~+#pRH_7S zio!)dAZ>vt+K`=svX?7d2=R+QPHp{Aw_*H)EG}tt8Wyv(HMmUk9y@-v?cI$XEg8r} zpgzfHWu~(jQE`VZW66bPVqYwLD#(jocrBFIUIdlC`q?zulct!)g20th#X_5Mb0b_y zQ}89184Z8(5H;7xvTE4|_aW34gB4K4m6gaolGQ4oQiU29u`&4OHkR)ixI9OZ-p=Iw zCicdjB`KlFG0Y>1Ws)5bE7CO}*7edmHZ8Rk-%{dbW8~&!BroDd7_+QFm5?#>0&GUA zL3?0m9|)a9aT#;*Ws3$Uo;oF0L&_D^iVFZ$&gFc*Q+7OB3M^uesoa-`eK?_{t^QkH zwDH>x<9NAw9B-azvemRd+#Civ&mR6d#M#ZOdGE3fpLMLEW@|D$vL0zxuT;2u0| zphYBN+4WP?rG*s1o8=<)4!kjLWL)A(GCU+}F6lPfNGzeFZ90k5OJ$c}riR=?$l`Xt z)E^q7Q&Cy`SAv?b=w@-{B5=~3eFp_>IvmH9pp32O)yVQy?FnU}xH*xXUSt@o(m{=j zlgppRh@{y7O6*Cvl0Atr>hmx?l-u+JQBuLiMn*p}#SzGl3=QF`q75@NzsRmu!umT8 zCtsCF1*6CQjdE|I+IjfJ$pdeV@g7TD>}b1*S>wD1HzwQN_G-!H)~&MDF!!|>+sJco zR)1-<=B6gn=D~v5S#U)XB)H7lWR`Z(89H@FXogejI)zX*t?$KgWf<|8Otp}T86kx= z%A-{TR9b+z(-pyyV^*5zNyQlwZe+0VWM%C6_+@i*)* zcDs1~g}JG%dd7G0nsw{>i|N+0TW8DpYUXCelo7ImTSlc1h7_`-YU>$}3s(&E;OtC{ z4?~ycS-*tFngJrDk_A_FVXsvda*Zd6HtD56U53g#Qxk(_1=8a zcN5dGXO8iWtSY*?Cu5Fqt{A<@(!#!4Rj>(mAy+Nx1UZ)Pc-DF&?sLmC-aLL&&cb8K zi>MgnnG3qi4CYj5#Dk}tmE3H;AOXv5_HC$Efr5 zHgs;Rs19@V?^l=a$0p%lPM?+Z?v}G~c%?hshQ>E2qrz&s-99%bjR|g8?3L5DHloYO zEc@{2V28HJ;XK=!a{mB_^ZC{f`JD1&&UGP{0{V7VB6++)CebpiehhSg6Gh98Hq!hx zk57FNq*7a4|6riIM`kzO@%&%NkDMnQ7wd; z$!BKPBURMy0|7>;lNTdgJZ9!A9A`OIiz{iPsO+Ja%7Jv3Bn4Alhenqav&eHb(P5l+ z&}DJDJhIi=?7*?e@9RH|=c+j6N{g+fkw(@=wcA&db_-1nQ)aTLN(!6i$4iR}DI-{) zJmbdfQR7g@Q9DH}@v5Vh1nFY0tsDke=|>sK=9)QKlLR}$p~Q^9X#;s9f$h{104u39 zGMzppn+s2-Uru;8DC2y^cEgfW;GC;Sb+6>|UNU1aTjm9Vf2+YFc%# z^znlRRc%uHf4Y9B@Ur5=%H%mRPn(Ak9!sPH$X8GE0K52-4OZ+1kbv=)h{Zeef%r5` zJh=-~pEDCuYBp>V!n`zX0aO#KQ54So<2Do~J1MUz$ewIKz83{)|(r?}txrrG7$Iaxff z68`|PrAEP8qn}o_9qPF{mY@u@ujr{ypU;sBh34D)T{~Ns$jzwQJV`W;;GVOAd#t*04_ElRgw_h??hJo0rKVLQ>5)p zdsKDlXKVwsu>Crx#BTFmbIAEreJ|e2(aO2MXNo@qJ^Iw#bdhH(i!7Zw7`AExbTrJW zeURufZ+UzTf^`Iu^H0L)Mh}{Fg^>aRNTyOXGU;SC#i>M=$Fbp5?0I;|GE9vg9hP|5 zu?yJhDz9PusutMBG>hFqhtd8tVVr~D+`}>adz@6%5@Y6L3AHWL0}X%?{K3$uJEE~6M&n?^ zV{<96kmSYTONBc`5=|pP@oQ0N$xXxp8Z(ZX7n|R&LQk`v9BE4tC>Qe5Nn-MjP z3`mcY!}lwP1)0xx8$n*XV&#B62GO%ykKpR&=iAQF3$11!+y4M0GUqzPSv9}h zYh2TTlRygGo@Ira80{tbn6{FF>q@DhNES_#p=phPNG3jW9-y-9W85Z?+KW$;v#h8247KmQ z>YaL4uI5&IsZk_Y71@PDK{ep)Rx)!jF~1cNd2n)LWTFE*!&RkQaY2silt$%uP*0&T zXUG`t$}(_dR#)=@9IQ2Kt@M^%wGvOL1;`#Pa}(k=^0_x4V42S|rL_B*n>jp-h{Nmg zyo|hsw-0C;dmEXxSN*3*LTOrk+ZLhr3c+~VWl2|+PvatFO5)6CTx6tvM$p8)*&4;96+#p!Vz zDqM?8GlgaG{$_fX6g4SZqjt3fS=xAKw)6d$2iYxmES-CQcoXHJ%E=#whaO^+VLW3~ zMX?X4sR^d&m9}MNLKN&sty%17oX<8!Gdy`>S0Q9Jtr;Qdtby~8psA3vs0^wvO{N}( zj$Up~cL**~!r$#YOJB8)wNvN*-^2NC00d~X(Eg$4D2q#gRuvulXbWui3NgVLn_44GsKXAq1cV%-_7Isxcip4;~X!?-9z#ilVuW?j`hoxl~ToN zqc;7tblXKV#!)I^E)=jsGS2#O)T+5d9IB|gdedw2fJG5nSlw6z@W4$9BB$a`w*`a3 zOEvBV1>T0>k_z{tSA?G=`bV0+L6fKhs4^;u;aHc}3o*pQ;FuEWg5#zQM3 zn2Q}~0cG+&lOt9mOMuzULW@S-R@U+4 zIEP}Ll|G{u#K%ekS8DPS^EXYC%&-sP{{R9b00J%)+!0`nYkEleNGzmL2YL&?%ej7g zJnc5Oy)FD%Hf8D#mmIF?$kbIoH8TtNIk98ZyxnF~nSViuWTjbv#W z1e3$l7$Zc27StM+!pQ>zXygboPDWE?e>zDJ$vY?J>X?!I`WgxN8S(O>K*dHMTfOje^ zf;gL>^oNIX{SvK0c$XI8+S%9jFfDRDl+vxCxrdppvc4|+*2F6TT6IUEBCsa8?WBgj z5G-*z%H~BmoKRtTWXxi^We*>L{{Y312NEKXg`Kh4L+K}8r3Qr+GAcAB9zWtetQIxw zr&C6ar(1LyLwu)j2s~?U6TkF-fbqUPwZepRd5+ZQ=~dOk$f8_=z3=2gwdyL0sZblB z-nzl#GSh4>UoD=zwA1`fje`~pQ$h@zCex|v0G z?RBK?o8eyFq3<~f2p=m=iO^)`XXIk2WiT#E6E=c8=nXEQ#nezc-nj{)yOUZxENnQX zSrSheqyGR5ux*P0y4IHSP}pgV14p30pr1@Q=2aZKbtud&w&@;SM`!m%S6Ro%`0?+; zS2b#ll@)sRw>vLWOR_q3il)#lW z`5>pGF4k~Nmh})`iNcauvRXV?ylH7m0*aIY3+4_tH%q7r)kT<=*>-$UMUEw!V+f7OF*D?OPV9Y37SEfo+>{dpb>4)HEkJq^7uB6*#(p zhzVRQ74CU@CTy&+CQLH;iXtR1s|H%qcO%5FMy> ztt1AcwUSM3z@DwT`PsD_UoO6JI31Nnx#oNMHV{@{cFwJv41t^0N!s@($l#qb5G*kP zRC-)V1nu*1 zvigWT%aUR+_~mH-0HJjvwcUGYAh;GN|n6J==%*-6CrCL@+K3H&%{$5h>~+y zWX7Ko*eRw4%>i0XD*_FgQCn8E>%fm3vW_u= z+#W4=*yEQyih(PmdiI-aU2?SUHm4r5NtCtM_jJH!HGqY&P#Q9FV5nwt9~l%bSMdQ- z7%ZC?LLtXs+czqpN~>qs=lz3^7JZX%vOPy~$l{(hlu@AR>be#-0g2t$i=p z#>*=YZ~ZNb%6aOuM?(0fvv~G%O*wS5p6EidGpk-8nl&!8CSt_2mGS2@=1_Au5M@_` zjVovY7phBq?C^u`0)|j)jS~-1p&2z`m1O z=8HOS*0WnK%IEltIRTh8*KWg;UDiuV)%Arex>fB%tg(HQ5<&no?nj*Y1af5MGUVlc z5GKB+$slT_2Wta!-odmb`VcvlVjYxVvy zGid!u`kVDf>T)#6T+f`;&gWlDI1t+5I$6cYAo&j+wNab4^YuwNYogJya^LhpifOJ` z;|mv;#W>H47x5E9q&B}ih_W34?e%%V*?KUe{G_)Ea^7jc#+xk0W!(i-f5QRHeq9<= z>9-a`f(;Tl`fdJ}_>LdbE*P8+Np}-BPeYek)33;}vokO>t=+48JSk}dZralfy*rn( zbB&q*0Cgx*E)_$hbK2Exncsxw82HcxSWB%t8}kY#IE#F&t!6^RBP$Su)q+MNW#CDX zFmD?{Iv1v$)U?VgQaH7ZKrE$HwR9m>@HBGyKi2;Mt3W(wTBP1~R#z(uwAo{P^V$KWN!((v!bhEZHW5*<>8fZ<55Ff5lW(W*|5ee2PbP*f1lg z@3nB(7nNa%;$H~qdnIo{FTa^ho%DG~AZ{;;s~_rLildU;;d>9?ilupm~6Aju0rNnMWGK8yNU@`3b7%{+^JN( zDoNW>iJJmIh=)N$r8KfSt=sR_N0YLU#0^9NzJlgzOMyhll_IxS%w5u|}saKnIgtZ8ZMVl~Fk>PT*j3n7rGp~?HA}YFz zMq0IQ$|YqUO)70g-dT_NzF#nxBV151i5;~xVpU_IRrG=ZpvE*mHl`HB4J&+arBrlt zx2ob3IA7Abyjz#?n%bOB-m5;M@<8P1sQp8KCepMe#pwx?pzCF>yViPd8upY%^*bkz zocEgR7>5=}-9XZH0^>}C$Vmm9g1%8f31g_(Z3bR5)*NPYEYPwYMeJ!)XaZN1E#9Uj zwFMTS3RznJ08JVgLxq*avsHz|vEsNpLyP2=S0%A(s7@hkO-nHh*48|h9U>c!_mx&r z0cyyo1JZ{_ogl~Yl`*k&#z2fIkTR3hD8CO?GxR9qZHAV3?-UP_I^$MGQ8H>W77A2= zFRst0%BOJ3Z*IC@>Hh%It`Y4A7Nu{IRlOSu%hAQH#w**W8#dInMQF2f)pW>I&S5xL zpoCS#vp*FeB+Y zg|jF{00Xv`ETr$K0BnO{S$GKJyxS`;>OUso*<4F6Z;tSeFRRTnIj;4=KYX$4Y2*gx zQAI-@G9!9y!t5v|pK9_N)>vx1G|P%CZdIDY3L`9Vt2BbjvnT|%oe za^~doY*@x)_;NW=i~uO4kO!171(j@BDp$;F%s9H`lsSLY?HulUu4JAbjQW|GTuU>E zKT>uI-J^f;{DW6e$2Pdun5$WHT|p&bf&&q0L}3Yeh6Z41dBK@tN#lP3V^WTh`A)WR zyG*nRDypL`)1AZ3c=2O~CkhE=WdH^$wBz`N zt%y6ur3%`Ddw>>hGRv7HvM#g$FeI@G`>l9-DM1@M1`Kr&q);YT(%pLb8a$8r9x1}; z)cz)=%_Z_X7OYUQkC!>m+~g}8O?c^q)k!w4YUJ!if*OpKuB5CBOdrP|#^R3vBwDnz zp@C@Q(9Fg`;wd^R-<&R>@wL&?NKYhOxpMI{W|hmvo-j#SkgC6vNJAEyPN}Fa ziBuh!fxuONqWQt}uOE?6`hkhaw;h_!OBlHsxA@)$T1wW96kISK377 zB(%<}Rtu-- zL}m*cc%aBjAaVqKU1G4LmO5029fu3gr}x_Ivc%#%K(*h2TQ@ga=KXp(boVJnn8?uM z{B-(&$SamFoqNm$F2XOhiy3V&_e99SPY@$xNsl^7sf%8@09s$+5DaVL0ui>?xMi&@ zPsYw+8%ViBA_AI5fC3@1Tlkk!F-<-oHmR{j>Y=**eO#Ob?DO6tHn^T0s~EgR?)s{0+#JlNg;>(lsd}8?B4#E%Q?I~S^C!WZDl|H2krm6eC@_LN z(gS5ADBvkKznhC%bas4rv*N^e8jCACtqUb&DorOq$gde@1F^0a{{TsYVi1iG~?YPD}S-7p!^a_Qsz zRvF3Fj~^|^WmI+!H8^suV1#JQi~!OZHJb!DEy4`ps~06Phlwt3LbEsqHqxavAs%N| z(7LxF%C3?$QgO9Y!@rlb;H5|mE>O~@n%tKkjN2V&Xl7ErNUs+Fla{pIr=N0-IwBSj zw~b?;1Q@WXIa;B}%!+kXm@xs!Ac9bo1I?#PRci}CFbYD8st#ya!HFy^%?mE-2rF8~ zq4L;e)u@8Si3G4LY9_T^kEcIQD`E2Bpv|0{4X~?~ma9CrzQ*NUeGAA0*Qyo%&~y@Z zNG+JfKWM4d_E>9FVmXJx7(Bx!#Hw{JljtF=+3Dtg! z_~nc$k;!ticDa52A-Qo>&vM=@BG%oVS-SF@x7C??yAfTjsHT4;hkTGKU9I?Qm-87P z$Cn9Z$(A_){6?e^mGd*ptw_HOgA349g(J;&AH;mimwp)%Jg18oJbI2W*RK4iv1wr1 zb*m{0uUD8FUzO?{8#j+@ayxpQJ53tArz7faU7WDwmTqx8tCa3t)BYoKJ%wpkE7}?# zZFa?$TD4HB#lQ^GQMfm7hfyN3~ zlbK>;94VSiE?#lWN#t3dRC-vj(uEubxRfrFL~3GdjMp4fa*rfMrD1;$$LQz#1Ea@p z@(NpgX`JILQ)2E#igo!SRPkE#u>foXP3W&d_1t|iouSavyt(*y95_-B2q+-mhUMc6 zBkL+nxKJ)N1y1Whv(7PuSb0E5au63TLwS5fRAy-7(WnYdWT9uJ>@ z?mu~(AIReuwZ|ioimq+luxkUce~}VI({&jsPgNnx_k`dJro$C6pA3v|3MkMS6nRys zX|0ykh3W?M@1zegx*SUzKIZY}k${c9Vxv{xT`Z*eNIqf)ujLdkfZjo0ldh%WJ4$~3 zbt=zheIr^mFY8r2{OxGX&%K~kNY_a;TU;T_hdK6$>&;W2Z#m7mOeq#NLMk{*GHDHM zV1FqlyxS-wk}c>0wWQ@d<;?TO;G;>rYR1)TR@MTN2;Im5K_M)gCYu9;eRukc$8+jC z>HfFVZ>B#?{{Vz`i|O+nEN`lL)Hs&4hq|96t%<#(TOW<=5`W&rC+A|$KUrSlFH4@4quL~5iYp(=4ED7e^qT>S0x9Q z_tYqm1(}_dH!zu%f`ynLAYdLqK5JUtG_`B4$6!g}p>yaRi_X^+0R&{yf>f!m?6(*Ez@=`zJ>1b$Z?`fLJin3*$!%D7j+|rRs zo8sZ%b2u_`B#h0G%c&3>2(hyu|$yJu>Sz%Y}sq%l3DYh!vbs}AL5lGi9C8J2B@@v>e_s*xw2!nR<z9bz;w{7?||y-4?v3QBc7`DBk$}j9pCpu1)lBhFH6w$2IwGdTwHUN`~C~ znw)=(Qm;pxxL#@6q}0Owx6R!K!zL-86DtQ8>ysd|X>x3)idR#( zK_W09?WuQBs2leVXknc)<{G>uN^~@QLhR2NLFbX9btC3_Yt#>rERI9`zXvUMM4o;8 zTzsp0Tz=}cu(G#My4jIKI^QkPYMNTHnhUp9#D(nlUCTC6vJ~#Ake@0POnKu(XpR_- zq+4b!VMPZtHXQ>qjX>!>YvIl&PmeY^cUewJbW${vr_9x&h#HvrwiJvtZk5E&Ez5Za zIpMaoIbA+E$!C2O->b^%I}c|IQPABf$jxp|%0W1suDv?RVX4gf*>Uu%MizxbVx~-( z)3U_I8Hfn>u4GjWL5PiXFw$%gtQ@JbI38Iciz*n)1!x0QRLZgHDhW!Fyg=3lpi1ck z0ext6>v7F0xVJJZqm*UpWl^C0SJ-BP?4++l_1T?sH7X*~?YHc>R7@3|A}lq`G6sb< z3_!@m7?-dM0Nu%Otc7Sert7g}>nTfB{O2&gR zmk?ve95Ca#U`(n2I~7ONH5V)j+Yd6D*YchznruH4DJC+@G|B;A3AY4-#TDmWR7@F?g@srHb`uZE9m_X!5(}TE%NqD_VwcE>3S9wwl-A^G(_6MY^lF z#ryvCb-}(qEU~oy34&9oY^(sX3sMH&n3hmL43-pvYzSeRIU|jx*BJnTtZ5}d2msUO z1$?Z^-dPz-c~yb6UY{|w&9v+zlKnm8d|gVbLo=3!UiT0yx*O_iX;h2bIVyc?HS(RL za7}N#H**InnpU!9< zqW(6&!N1A@5-4((1FHE*AH+Jtlp28pPy^?G*68|=^j?Q2czsb{IOUq!yeo@i(%8#I zZH?p@wDcy-UoT~YG~EGNbz-TMWgQ6`#Wo_9byYf~PzA6O z5`JUlY9wmX*IKwHIeZfN5-|KGSDAGR@WZ~Pj1&M}SSw>?EC2+6y!r?Ahy6~Y5V;rn zy821OxR!PMk;ZRwTtBJbOx4H3W9|bP!=;{`dsjHlRqYK--?BEXjY9Np9*UI8>?ucw zgD{^cvKV2IpA006b-0xzCr`*!=`;Xd-MA`D{{RvtG9ZRX1-WS5l(-s|lc$xGf_LA) z$~b3Tz5bp)>Gsj|^D3Q=!oQ#^A2B+ zA1~$p7%7jJlF2LsPk`zjXG=n-Ns2~c8A7E{=-og8%uvLpD3vrMjALLn47*A!3Kp&b zS_4l&IQ4s$ax~Q9+6Aw2!z353b?rCbqRYx<+9KxBIQE!xR+>UeMowZn^6CZ!qG4k} z<72}gg%*H7U8`c7S8%%n*1Pa#JnngiE^-4jYO{hx)Qrs$AQMB%Ka>skyWsojPcGj+ zUBYa#`;2Vp9oAO&8VQRSwzKr9noUd=puXy&W=I$%0}?AG#P#UjO@ob%pO+*kRry|q zgz9a!W2B3%CdeQFNZg%U@wnyl%GtRRc!WHP<&Uih?RUQ`7A2RV+o0Qz^@0AKR6q15 z6v9-RGebWwc$TA|efqj|vNdj6eb#w7kXLSz3jN4Zy@kR-aR=wW#+CCV#=@DZ2p1G6 zU8_`LLf-AD?REgIyYaAv1|BSP#7UKsOJ?4{B>?OIq0wupzBShr&Z)d|%_PI8GeNa$ z{LINFrKqN{YZ)YG6AXqNc|e<1GD9OCGEo97(;C@Ea43^hti)IZUrzVjiaYRIJ2nzM z>3uA00d~ryox!g`Rj{LDgB==chkbwU;x z$P7qPRi)ew7i9ndP*MQu0B!hRnG%H(n|UB$6^Xr>X|)cGcfF1J8x}YM=lX8ryzsbP z1y^>PzP`* zo8H*bB-ah`avo|f2B2eG0*Tb6tk%SX^6f*g;;WPCTRIguPY0 zX14=-AOJO38|*y*;MHGQv7uzu3a$al&&Y~biZUZsnc_4*l+pSFW2hV1 zyA?*5b`hh4t3)D1N1|3~)^Mu36or$=UGOt7&XmPnl zG>{;P^E^jls-UYx7eP`5^)_{C+zPGiaPK~LLro(|_*O{N7HTUdy;`V)&}pDlQ8o#p z5T_$DJa3fhTG++pb-5#*pK(+hS2;X(&g-+O<{+uaEm1sXu$x>iwJXrJv9KV~ z6^D?XK2+joX?zIdlxigZ029QLJzrfbwN~VxN-q#bkV44{A(lfKrLQSSWUCwXayKVn zz3iN&^^V%~>s7%z6zXOqaRgOHZdZ4Xjob%X@wqn1%4toj5iMH*#0`)(5cLoySy+-W z9BRHBb7h_N$XH6uy4=a(WWKf_gfS?nyfHu81>tvBesVDUX+>`0|)Lu#S z*NpR?XJ3kPJpTZxT!~4!uDva8G@RXDD8zBDFUapxJq+$LOu1@UmRWnt-$e@kj%n~!RuBicO2g>#e)legPVhJLE(Q>HUDmD#XSABT?=kRVOFWFc z%fgHCP^PA`7tOG1EC!=M1|o%O1PTJER|8{ZJK?5LMG_F}RBK9tXjvt0&6OaVyS@0i z`ejQ#mS*oP`xRT<+^Nkgy2Z!eZF(_JSvjKoyzsa+>D_L2H9Gd6?Gvuo7_DsHg&}Dd z6Dn+(aWE%7Br?e?YM9>YS4L|_a2M0VU40#!`6C9DEx~Ta9AOqz$eMuHc zQ@W6N`aJzj8@zuXHpQWwjK))%nBhk)d0_2M9htRy)YS?xA9&06TQcaFXNZVFc*Mlt z%r0Ck09dFpGK$y_HslVPm{2CZRRB=Cs|+Mrd5p1wOks`Ly67(Ml-U3ttWR2{miH## zwZvI|#-rHn9ej$FBipRC;8)S2&%7K+N(NH$j=HeW*HLY#ZhJY5jCGAP%@9(>L2ojXc5D_>Jf(rJveIt-d`>0) zn|Zg??9MI58Oba`XlRApbXd>S%HvdMS>yaR;^IZY!l|OsAsOg;Km}uG&Tsi#Eq6A< ziysAYtj{L2Buh@ERT!*95oQ(IqrE!VMXCdqm8d?KPXbY-+Gg-*3oB9Plk+mk2F zWYGYT!Pf%%i^=uzKAZEmSgBiIo_!Qo)E$b{XxFcuS6fS#8se5XK+ChUD}Nx_tK#{z zzX1ZYYLf%awq*G^m|i1LmL~)*-P3jMt>-(b8&&bGju^4=@)Z*FN~|?`w+eP3?8C}7 zV0xZB{XzPJ%3ZNeoM=KQ4IGX#nibNu)kP~d-JW(rI+AXLRgeK=Ns$ncj}I8?Q{}TZ z0?dcOka&q}-D_b@s0tebDDQikJUoV>&un_}BR&+KZn~RuWpvoR=-BqI5#Q=>>US{u zL6^!hxPFsXn*8UEVIkMwa?Oh9_t5@HboT|{wIMI0zR z%4Ui!{{YbbC~B&rRB6<-bnGjI{KqC%mtBBb8D!XhGK4AC>?0D&rpB$vCyar!{-=Jc zS*P^J3g(7Q)B2mlcf0%DaV|xL0u}L0W$ON~n<35yAWfW;2$ze}Zu>@{SYTu9aHN-Nj z->bqlZyW6BI=y8Z34)}<)5HC#&|ONv3Qg8kxYas91#J-%CClPlB$*gx;JW!9a6=U( zZ^&aLQ2|L)zK{VlNZ4_9pA!QtIn=RfDhN^s@ihQ!5cT*YRMYP=!Zc@(h3cO4=Tzs-EzkJ^tmvULw`-7PXj;C#+gE7<7aHxcUXeb+kft!`CD9{b zWyNp9P$p&+jXN>X4~sz1EYC*%)CEzXH?R)_^SPcpsC3XW&avGK3I}bgt(qXHB+`IL z;gL`1-WL@5X>Uh2kn=~YHoff&Svs4crI)#57fWa9{W#ZMsxt4kouMFDIGDG_vS`Hh><2ghXIEZZECf@7$7Z#OGOfxV)}Nk}%m~ z;U6I@ahzw?ciCfTFpFM-)}k2u9>@Ccik?q5olKvKN(a*%45z! z9T61Fm#$?lRJl1P0#XbM0?E_NO|t>3u9Y>U3aS;yL0ovT@&5oH5F&pZr(Y-s%1)k| zi0XQq-;8_pPwAHyp@m11u@-fCE`KWLWsSeG)o5wpplxpw^YU86K%*#9r>pIZ7=sJ% zmI1Wkf|CX)mIo#=Ah{R^^8uxrfWC|8Yaf+Y4zp#E@&VRV#v(pnEtk*@a{OjR}%zn`T)q z4qInx%y^@MeBi9cHK2?b4N-YKGGpk{{U;; znG;B1UlW)qV)Qf;+DkIJGd7|{*(0c;JwIPN~JR; zB!4f0A%o2DnLJ!~j(I7I9W4q-tEYXfc4NC9%s2y?35D@dRU!dSdC?M5vYzX4J7~U9>lJ zR$xmg7+^}hvRD*o4==_^v$4@i!l95Y>;o5VuJ;8&2iL9ei~PqZ!-q34X?%=YwcFbE%6 z2YZTSl|I+FNkIaLZ6>_RY}|Rgc=^2JGC470NBk&ekwXa`6p`S_ zOBHxcn^L#ArUIz_cD8pcMwYiF zSViSNwejTS<($UIou!Z|^IaPdkWBy<*lg4)wg7REF~b0XVTB?>+bXY=e-sg2NYYJ> z`qkYI0=fSH-cjMa>9uuq)>QTQt$NZ{0q#In#nd|f)$1xdE0xY&NDmi80E~b{2Z)Fn zjN=@sa_X|85XSW>T|&>zYCsA>6a{a=*qTm6Y!E9LUF-^@tSO=L(bUA)JCbZ!;IDwN z59vqK4ojqw-qQM;&OhmXTsx1ue>(0%@oBt8IYn%1Rlb&)9cyB*x~jq_S90ELX}jeQ z;Nf7MJ|O0YOv>eouuxfipnwP}DD@U=so_sCQ$ANRw($P|%M>&v0)nNVNf)G&q#G(u zl0xbRfZ(5$Q>l?h>Q5KRtePBfms>i{Acx-P-Oty{!qKr(;WA+@L911uay|-B1p9`H)pv3-O;P>z>vst(*<)BWiSusacm53$gN_9&;*Lp zt8fQS5~oNuOOa+ntz@A(Rxm0%Cc_n>Mdu^%>TnhnY5rRf& zWLnO?a%RiWw)S~Q-x|2e;H^R^9Eq^DC6-g?BqPz-0u(I( zx_q_NcO=>3i6mpoz+WJSPY6|#K`i8w#hA9L-un%>F#18vcD5;UEZ#!Jaxq>10IFF{ zx3n#@dg8d(FODIY+mBP159>UM#b3rLeaTA#s0Z}DUem}|30Uh{v1D_1vGJNZUHqyP zY@=Xoir^`+;_))bT_+nNDAbLuRsk=Y)RsPG*suT|_ouMP1sd260_Hh678^RKU45Bev$LuJ;C^Wcc+K* zt~vF8>W%(6e@9N{URNgiYOXV-#g&SQxH6n2)U&02Of749>}Vdw4?6X)^q!(=c9So8v> zHI!YQEYYJ7yZoe+*2(Tq8n_cu!7*|q3=q`-LdhZmKozJeiXwoaLxf)byK%SjZD!S} zPByG@G1aF|El|(5Xa1Yd*_a>{2Y#{KK1OS(CwZONE2qwddNnsBn)Pc8CtHle|3fLf<2JG*` z$1byEqR2v>Dgg@GRHHR6wQ8fVJwO{B&DC!5-JQ*MaZAieM!w|GjmMyrCT|+X=hS`PK9fJ%PR$nri&sjgL&eA^5tb_LaL4^{HIV-qVAP} z^AETn-KXSvFE1vJc@M$=7^%JJmpPmSVB8Z(Bq zk%J2g2n5|J1lo Date: Wed, 17 Feb 2016 17:28:40 +0100 Subject: [PATCH 04/51] WIP: committed changes so far Signed-off-by: Tom Van Herreweghe --- .coveralls.yml | 1 + .travis.yml | 31 + CHANGELOG.rst | 7 + composer.json | 2 +- composer.lock | 2151 +++++++++++++++++ ...ptException.php => InterruptException.php} | 0 src/PHPExif/Reader.php | 30 +- src/PHPExif/ReaderInterface.php | 52 + .../UnknownAdapterTypeExceptionTest.php | 39 + tests/PHPExif/ReaderTest.php | 79 +- 10 files changed, 2347 insertions(+), 45 deletions(-) create mode 100644 .coveralls.yml create mode 100755 .travis.yml create mode 100644 composer.lock rename src/PHPExif/Exception/{InteruptException.php => InterruptException.php} (100%) create mode 100644 src/PHPExif/ReaderInterface.php create mode 100644 tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..7a18ce2 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +src_dir: src diff --git a/.travis.yml b/.travis.yml new file mode 100755 index 0000000..d126f4f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - 7.0 + +#matrix: +# allow_failures: +# - php: 5.6 + +script: + - mkdir -p build/logs + - php vendor/bin/phpunit -c phpunit.xml.dist + - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml + - ./vendor/bin/phpcs --standard=PSR2 ./lib/ + +before_script: + - composer install --prefer-source + +after_script: + - php vendor/bin/coveralls -v + +before_install: + - composer self-update + - wget http://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-9.90.tar.gz + - tar -zxvf Image-ExifTool-9.90.tar.gz + - cd Image-ExifTool-9.90 && perl Makefile.PL && make test && sudo make install + - cd .. && rm -rf Image-ExifTool-9.90 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c8fba32..7330a5a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,13 @@ CHANGELOG ----- * PSR-4 compliant +* Immutable Exif data class +* Immutable Iptc data class +* Custom exception classes +* Adapters are now considered as namespaces which implement certain behavior +* Refactored Native mapper class +* Introduced Configuration class to configure the Reader adapters +* Created & used interfaces as typehints throughout the code 0.4.0 ----- diff --git a/composer.json b/composer.json index edd40fe..23b0154 100755 --- a/composer.json +++ b/composer.json @@ -25,6 +25,6 @@ }, "minimum-stability": "dev", "autoload": { - "psr-4": { "PHPExif\\": "src/" } + "psr-4": { "PHPExif\\": "src/PHPExif/" } } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..2129860 --- /dev/null +++ b/composer.lock @@ -0,0 +1,2151 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "a21b65b95d8bbe995e9e27fb805ed85d", + "content-hash": "7cfc59e9aed93dbd6468e13bc1896af9", + "packages": [], + "packages-dev": [ + { + "name": "doctrine/collections", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "866e100a425b8b73d15393fd081c6bf067f05bf9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/866e100a425b8b73d15393fd081c6bf067f05bf9", + "reference": "866e100a425b8b73d15393fd081c6bf067f05bf9", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "array", + "collections", + "iterator" + ], + "time": "2015-09-11 15:24:21" + }, + { + "name": "doctrine/instantiator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "gitonomy/gitlib", + "version": "v0.1.8", + "source": { + "type": "git", + "url": "https://github.com/gitonomy/gitlib.git", + "reference": "f575b8f7da917ade7890c6aa705fa22545690389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/gitonomy/gitlib/zipball/f575b8f7da917ade7890c6aa705fa22545690389", + "reference": "f575b8f7da917ade7890c6aa705fa22545690389", + "shasum": "" + }, + "require": { + "symfony/process": "^2.3|^3.0" + }, + "require-dev": { + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Add some log" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Gitonomy\\Git\\": "src/Gitonomy/Git/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexandre Salomé", + "email": "alexandre.salome@gmail.com", + "homepage": "http://alexandre-salome.fr" + }, + { + "name": "Julien DIDIER", + "email": "genzo.wm@gmail.com", + "homepage": "http://www.jdidier.net" + } + ], + "description": "Library for accessing git", + "homepage": "http://gitonomy.com", + "time": "2015-12-01 22:25:57" + }, + { + "name": "guzzlehttp/guzzle", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "74fc3909170d66f3e93719ae025b79faea1f49f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/74fc3909170d66f3e93719ae025b79faea1f49f5", + "reference": "74fc3909170d66f3e93719ae025b79faea1f49f5", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "~1.0", + "guzzlehttp/psr7": "~1.1", + "php": ">=5.5.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0", + "psr/log": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.1-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2015-12-29 21:28:50" + }, + { + "name": "guzzlehttp/promises", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/b1e1c0d55f8083c71eda2c28c12a228d708294ea", + "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2015-10-15 22:28:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982", + "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "time": "2015-11-03 01:34:55" + }, + { + "name": "pdepend/pdepend", + "version": "2.2.2", + "source": { + "type": "git", + "url": "https://github.com/pdepend/pdepend.git", + "reference": "d3ae0d084d526cdc6c3f1b858fb7148de77b41c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/d3ae0d084d526cdc6c3f1b858fb7148de77b41c5", + "reference": "d3ae0d084d526cdc6c3f1b858fb7148de77b41c5", + "shasum": "" + }, + "require": { + "php": ">=5.3.7", + "symfony/config": "^2.3.0", + "symfony/dependency-injection": "^2.3.0", + "symfony/filesystem": "^2.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0.0,<4.8", + "squizlabs/php_codesniffer": "^2.0.0" + }, + "bin": [ + "src/bin/pdepend" + ], + "type": "library", + "autoload": { + "psr-0": { + "PDepend\\": "src/main/php/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Official version of pdepend to be handled with Composer", + "time": "2015-10-16 08:49:58" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpmd/phpmd", + "version": "2.2.3", + "source": { + "type": "git", + "url": "https://github.com/phpmd/phpmd.git", + "reference": "5eeb5a4d39c8304910b33ae49f8813905346cc35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/5eeb5a4d39c8304910b33ae49f8813905346cc35", + "reference": "5eeb5a4d39c8304910b33ae49f8813905346cc35", + "shasum": "" + }, + "require": { + "pdepend/pdepend": "~2.0", + "php": ">=5.3.0", + "symfony/config": ">=2.4", + "symfony/dependency-injection": ">=2.4", + "symfony/filesystem": ">=2.4" + }, + "require-dev": { + "phpunit/phpunit": "*", + "squizlabs/php_codesniffer": "*" + }, + "bin": [ + "src/bin/phpmd" + ], + "type": "project", + "autoload": { + "psr-0": { + "PHPMD\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Manuel Pichler", + "email": "github@manuel-pichler.de", + "homepage": "https://github.com/manuelpichler", + "role": "Project Founder" + }, + { + "name": "Other contributors", + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", + "role": "Contributors" + } + ], + "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", + "homepage": "http://phpmd.org/", + "keywords": [ + "mess detection", + "mess detector", + "pdepend", + "phpmd", + "pmd" + ], + "time": "2015-05-27 18:16:57" + }, + { + "name": "phpro/grumphp", + "version": "v0.7.0", + "source": { + "type": "git", + "url": "https://github.com/phpro/grumphp.git", + "reference": "6d675b47011f0bcf1cb4ec6644b731ed5a416714" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpro/grumphp/zipball/6d675b47011f0bcf1cb4ec6644b731ed5a416714", + "reference": "6d675b47011f0bcf1cb4ec6644b731ed5a416714", + "shasum": "" + }, + "require": { + "composer-plugin-api": "~1.0", + "doctrine/collections": "~1.2", + "gitonomy/gitlib": "~0.1.7", + "php": ">=5.3.6", + "symfony/config": "~2.4|~3.0", + "symfony/console": "~2.6|~3.0", + "symfony/dependency-injection": "~2.4|~3.0", + "symfony/event-dispatcher": "~2.5|~3.0", + "symfony/filesystem": "~2.4|~3.0", + "symfony/finder": "~2.4|~3.0", + "symfony/options-resolver": "~2.6|~3.0", + "symfony/process": "~2.4|~3.0", + "symfony/yaml": "~2.4|~3.0" + }, + "require-dev": { + "composer/composer": "^1.0-alpha11", + "fabpot/php-cs-fixer": "~1.0", + "phpspec/phpspec": "~2.4", + "roave/security-advisories": "dev-master@dev", + "squizlabs/php_codesniffer": "~2.3" + }, + "suggest": { + "behat/behat": "Lets GrumPHP validate your project features.", + "codeception/codeception": "Lets GrumPHP run your project's full stack tests", + "fabpot/php-cs-fixer": "Lets GrumPHP automatically fix your codestyle.", + "phpspec/phpspec": "Lets GrumPHP spec your code.", + "phpunit/phpunit": "Lets GrumPHP run your unit tests.", + "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues.", + "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code." + }, + "bin": [ + "bin/grumphp" + ], + "type": "composer-plugin", + "extra": { + "class": "GrumPHP\\Composer\\GrumPHPPlugin" + }, + "autoload": { + "psr-0": { + "GrumPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Toon Verwerft", + "email": "toon.verwerft@phpro.be" + }, + { + "name": "Alexander Deruwe", + "email": "alexander.deruwe@phpro.be" + } + ], + "description": "A composer plugin that enables source code quality checks.", + "time": "2015-12-11 12:13:59" + }, + { + "name": "phpspec/prophecy", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "e55e3e32a870bd4f05425fa4f717b52bd40e5659" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e55e3e32a870bd4f05425fa4f717b52bd40e5659", + "reference": "e55e3e32a870bd4f05425fa4f717b52bd40e5659", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-12-28 13:26:33" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-10-06 15:47:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.3.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "File/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2013-10-10 15:34:57" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2015-06-21 08:01:12" + }, + { + "name": "phpunit/php-token-stream", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/cab6c6fefee93d7b7c3a01292a0fe0884ea66644", + "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-09-23 14:46:55" + }, + { + "name": "phpunit/phpunit", + "version": "4.5.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d6429b0995b24a2d9dfe5587ee3a7071c1161af4", + "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "~1.3,>=1.3.1", + "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpunit/php-file-iterator": "~1.3.2", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "~1.0.2", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.1", + "sebastian/environment": "~1.2", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.5.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2015-03-29 09:24:05" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-10-02 06:51:40" + }, + { + "name": "psr/http-message", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "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", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2015-05-04 20:22:00" + }, + { + "name": "psr/log", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d8e60a5619fff77f9669da8997697443ef1a1d7e", + "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-01-06 21:40:42" + }, + { + "name": "satooshi/php-coveralls", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/satooshi/php-coveralls.git", + "reference": "8384919da59b11763db611dccc5ca141f32533c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/8384919da59b11763db611dccc5ca141f32533c5", + "reference": "8384919da59b11763db611dccc5ca141f32533c5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5", + "psr/log": "^1.0", + "symfony/config": "^2.4|^3.0", + "symfony/console": "^2.1|^3.0", + "symfony/stopwatch": "^2.2|^3.0", + "symfony/yaml": "^2.1|^3.0" + }, + "require-dev": { + "apigen/apigen": "^2.8", + "pdepend/pdepend": "^2.2", + "phpmd/phpmd": "^2.0", + "phpunit/php-invoker": "^1.1", + "phpunit/phpunit": "^4.0", + "sebastian/finder-facade": "^1.1", + "sebastian/phpcpd": "^1.4", + "squizlabs/php_codesniffer": "^1.4", + "theseer/fdomdocument": "^1.6" + }, + "suggest": { + "symfony/http-kernel": "Allows Symfony integration" + }, + "bin": [ + "composer/bin/coveralls" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.7-dev" + } + }, + "autoload": { + "psr-4": { + "Satooshi\\": "src/Satooshi/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kitamura Satoshi", + "email": "with.no.parachute@gmail.com", + "homepage": "https://www.facebook.com/satooshi.jp" + } + ], + "description": "PHP client library for Coveralls API", + "homepage": "https://github.com/satooshi/php-coveralls", + "keywords": [ + "ci", + "coverage", + "github", + "test" + ], + "time": "2015-12-05 02:06:10" + }, + { + "name": "sebastian/comparator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "6e7133793a8e5a5714a551a8324337374be209df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", + "reference": "6e7133793a8e5a5714a551a8324337374be209df", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-12-02 08:37:27" + }, + { + "name": "sebastian/exporter", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "f88f8936517d54ae6d589166810877fb2015d0a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f88f8936517d54ae6d589166810877fb2015d0a2", + "reference": "f88f8936517d54ae6d589166810877fb2015d0a2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-08-09 04:23:41" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/recursion-context", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-11-11 19:50:13" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21 13:59:46" + }, + { + "name": "symfony/config", + "version": "2.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", + "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/filesystem": "~2.3|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2016-01-03 15:33:41" + }, + { + "name": "symfony/console", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0360a690902c60a0aeda2b4da0bcf1098ee849ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0360a690902c60a0aeda2b4da0bcf1098ee849ce", + "reference": "0360a690902c60a0aeda2b4da0bcf1098ee849ce", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2016-01-15 09:32:41" + }, + { + "name": "symfony/dependency-injection", + "version": "2.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "ba94a914e244e0d05f0aaef460d5558d5541d2b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ba94a914e244e0d05f0aaef460d5558d5541d2b1", + "reference": "ba94a914e244e0d05f0aaef460d5558d5541d2b1", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/expression-language": "<2.6" + }, + "require-dev": { + "symfony/config": "~2.2|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/yaml": "~2.1|~3.0.0" + }, + "suggest": { + "symfony/config": "", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2016-01-12 17:46:01" + }, + { + "name": "symfony/event-dispatcher", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "c021a1c4f1d0a7594542c3d1f231d71677ab4ea5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c021a1c4f1d0a7594542c3d1f231d71677ab4ea5", + "reference": "c021a1c4f1d0a7594542c3d1f231d71677ab4ea5", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2016-01-14 07:58:06" + }, + { + "name": "symfony/filesystem", + "version": "2.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", + "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2016-01-13 10:28:07" + }, + { + "name": "symfony/finder", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "45571dd5f5b512a650949f089baf07edc5575b53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/45571dd5f5b512a650949f089baf07edc5575b53", + "reference": "45571dd5f5b512a650949f089baf07edc5575b53", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2016-01-15 09:32:41" + }, + { + "name": "symfony/options-resolver", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "5d3eea990b8e1799e305ab32f1369ff89b3c2b72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d3eea990b8e1799e305ab32f1369ff89b3c2b72", + "reference": "5d3eea990b8e1799e305ab32f1369ff89b3c2b72", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2016-01-03 15:35:40" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "d7f01c96a4dde264682cf36c28e62086c77a09d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d7f01c96a4dde264682cf36c28e62086c77a09d4", + "reference": "d7f01c96a4dde264682cf36c28e62086c77a09d4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-01-13 07:16:33" + }, + { + "name": "symfony/process", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "1cba8f04eb0a9e38184a8003e927a5fb2d62158a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/1cba8f04eb0a9e38184a8003e927a5fb2d62158a", + "reference": "1cba8f04eb0a9e38184a8003e927a5fb2d62158a", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2016-01-06 10:01:46" + }, + { + "name": "symfony/stopwatch", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "00045f8fd6f14b7c6c1be2434828ed5c57fd7a99" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/00045f8fd6f14b7c6c1be2434828ed5c57fd7a99", + "reference": "00045f8fd6f14b7c6c1be2434828ed5c57fd7a99", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2016-01-03 15:35:40" + }, + { + "name": "symfony/yaml", + "version": "2.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/34c8a4b51e751e7ea869b8262f883d008a2b81b8", + "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-01-13 10:28:07" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.3.0" + }, + "platform-dev": [] +} diff --git a/src/PHPExif/Exception/InteruptException.php b/src/PHPExif/Exception/InterruptException.php similarity index 100% rename from src/PHPExif/Exception/InteruptException.php rename to src/PHPExif/Exception/InterruptException.php diff --git a/src/PHPExif/Reader.php b/src/PHPExif/Reader.php index aad6dfb..206cf8f 100644 --- a/src/PHPExif/Reader.php +++ b/src/PHPExif/Reader.php @@ -9,10 +9,10 @@ * @package Exif */ -namespace PHPExif\Data; +namespace PHPExif; use PHPExif\Adapter\Native\Reader\Reader as NativeReader; -use PHPExif\Exception\NoAdapterException; +use PHPExif\Adapter\ReaderInterface as AdapterReaderInterface; use PHPExif\Exception\UnknownAdapterTypeException; /** @@ -23,11 +23,8 @@ * @category PHPExif * @package Exif */ -final class Reader +final class Reader implements ReaderInterface { - const TYPE_NATIVE = 'native'; - const TYPE_EXIFTOOL = 'exiftool'; - /** * The current adapter * @@ -40,15 +37,13 @@ final class Reader * * @param \PHPExif\Adapter\ReaderInterface $adapter */ - public function __construct(ReaderInterface $adapter) + public function __construct(AdapterReaderInterface $adapter) { $this->adapter = $adapter; } /** - * Getter for the reader adapter - * - * @return \PHPExif\Adapter\ReaderInterface + * {@inheritDoc} */ public function getAdapter() { @@ -56,15 +51,10 @@ public function getAdapter() } /** - * Factory for the reader - * - * @param string $type - * @return Reader - * @throws UnknownAdapterTypeException When given type is invalid + * {@inheritDoc} */ public static function factory($type) { - $classname = get_called_class(); switch ($type) { case self::TYPE_NATIVE: $adapter = NativeReader::withDefaults(); @@ -77,14 +67,14 @@ public static function factory($type) default: throw UnknownAdapterTypeException::forType($type); } + + $classname = get_called_class(); + return new $classname($adapter); } /** - * Reads & parses the EXIF data from given file - * - * @param string $file - * @return \PHPExif\Data\Exif + * {@inheritDoc} */ public function read($file) { diff --git a/src/PHPExif/ReaderInterface.php b/src/PHPExif/ReaderInterface.php new file mode 100644 index 0000000..c82e4fb --- /dev/null +++ b/src/PHPExif/ReaderInterface.php @@ -0,0 +1,52 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif; + +use PHPExif\Exception\UnknownAdapterTypeException; + +/** + * ReaderInterface + * + * Public API for reading EXIF data + * + * @category PHPExif + * @package Exif + */ +interface ReaderInterface +{ + const TYPE_NATIVE = 'native'; + const TYPE_EXIFTOOL = 'exiftool'; + + /** + * Getter for the reader adapter + * + * @return \PHPExif\Adapter\ReaderInterface + */ + public function getAdapter(); + + /** + * Factory for the reader + * + * @param string $type + * @return ReaderInterface + * @throws UnknownAdapterTypeException When given type is invalid + */ + public static function factory($type); + + /** + * Reads & parses the EXIF data from given file + * + * @param string $file + * @return \PHPExif\Data\Exif + */ + public function read($file); +} diff --git a/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php new file mode 100644 index 0000000..81489b2 --- /dev/null +++ b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php @@ -0,0 +1,39 @@ + + */ +class UnknownAdapterTypeExceptionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @group exception + * @covers \PHPExif\Exception\UnknownAdapterTypeException::forType + */ + public function testForTypeReturnsInstance() + { + $instance = UnknownAdapterTypeException::forType('foo'); + + $this->assertInstanceOf( + '\\PHPExif\\Exception\\UnknownAdapterTypeException', + $instance + ); + } + + /** + * @group exception + * @covers \PHPExif\Exception\UnknownAdapterTypeException::noInterface + */ + public function testnoInterfaceReturnsInstance() + { + $instance = UnknownAdapterTypeException::noInterface( + 'foo', + 'bar' + ); + + $this->assertInstanceOf( + '\\PHPExif\\Exception\\UnknownAdapterTypeException', + $instance + ); + } +} diff --git a/tests/PHPExif/ReaderTest.php b/tests/PHPExif/ReaderTest.php index 450ed67..bceeede 100644 --- a/tests/PHPExif/ReaderTest.php +++ b/tests/PHPExif/ReaderTest.php @@ -1,4 +1,6 @@ */ @@ -6,51 +8,80 @@ class ReaderTest extends \PHPUnit_Framework_TestCase { /** * @group reader - * @covers \PHPExif\Reader::__construct + * @covers \PHPExif\Reader::getAdapter */ - public function testConstructorCallsSetData() + public function testGetAdapterReturnsFromProperty() { - $mock = $this->getMockBuilder('\\PHPExif\\Reader') - ->disableOriginalConstructor() - ->getMock(); $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') ->getMock(); + $reader = new \PHPExif\Reader($adapter); - // now call the constructor - $reflectedClass = new ReflectionClass('\\PHPExif\\Reader'); - $constructor = $reflectedClass->getConstructor(); - $constructor->invoke($mock, array($adapter)); - - // verify if set in property $reflProperty = new \ReflectionProperty('\\PHPExif\\Reader', 'adapter'); $reflProperty->setAccessible(true); - $actual = $reflProperty->getValue($mock); + $reflProperty->setValue($reader, $adapter); $this->assertSame( $adapter, - $actual + $reader->getAdapter() ); } /** * @group reader - * @covers \PHPExif\Reader::getAdapter + * @covers \PHPExif\Reader::factory + * @expectedException \PHPExif\Exception\UnknownAdapterTypeException */ - public function testGetAdapterReturnsFromProperty() + public function testFactoryThrowsExceptionForUnknownType() { - $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') - ->getMock(); - $reader = new \PHPExif\Reader($adapter); + $type = 'foo'; + $instance = Reader::factory($type); + } - $reflProperty = new \ReflectionProperty('\\PHPExif\\Reader', 'adapter'); - $reflProperty->setAccessible(true); + /** + * @group reader + * @covers \PHPExif\Reader::factory + */ + public function testFactoryForNativeReturnsInstance() + { + $type = Reader::TYPE_NATIVE; + $instance = Reader::factory($type); - $relfProperty->setValue($reader, $adapter); + $this->assertInstanceOf('\\PHPExif\\Reader', $instance); + } - $this->assertSame( - $adapter, - $reader->getAdapter() + /** + * @group reader + * @covers \PHPExif\Reader::factory + */ + public function testFactoryForNativeReturnsInstanceWithCorrectAdapter() + { + $type = Reader::TYPE_NATIVE; + $instance = Reader::factory($type); + $adapter = $instance->getAdapter(); + + $this->assertInstanceOf( + '\\PHPExif\\Adapter\\Native\\Reader\\Reader', + $adapter ); } + + /** + * @group reader + * @covers \PHPExif\Reader::read + */ + public function testReadForwardsToAdapter() + { + $file = '/path/to/a/file'; + $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') + ->getMock(); + $adapter->expects($this->once()) + ->method('read') + ->with( + $this->equalTo($file) + ); + + $reader = new \PHPExif\Reader($adapter); + $reader->read($file); + } } From 657aedda570adfcf8389ab37b972e296876e2242 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 19:56:18 +0100 Subject: [PATCH 05/51] Exclude vendor from code coverage Signed-off-by: Tom Van Herreweghe --- phpunit.xml.dist | 3 +++ 1 file changed, 3 insertions(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 8ef93dc..e7811f7 100755 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,6 +16,9 @@ *Interface.php + + ./vendor + From f591f1cee076375577ea5d78eb738586d2af1b00 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 20:00:37 +0100 Subject: [PATCH 06/51] Fixed missing semicolon Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/Reader/Mapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PHPExif/Adapter/Native/Reader/Mapper.php b/src/PHPExif/Adapter/Native/Reader/Mapper.php index 86d0b29..9ea6f54 100644 --- a/src/PHPExif/Adapter/Native/Reader/Mapper.php +++ b/src/PHPExif/Adapter/Native/Reader/Mapper.php @@ -141,7 +141,7 @@ public function map(array $data) try { $this->handleSection($field, $value, $mappedData); $this->skipUnknownField($field); - $this->doCustomManipulation($field, $value) + $this->doCustomManipulation($field, $value); } catch (InterruptException $e) { continue; } From 026be01800071b46755de0a98fc6c45fa800303a Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 20:04:20 +0100 Subject: [PATCH 07/51] Unit test for NoExifDataException Signed-off-by: Tom Van Herreweghe --- .../Exception/NoExifDataExceptionTest.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/PHPExif/Exception/NoExifDataExceptionTest.php diff --git a/tests/PHPExif/Exception/NoExifDataExceptionTest.php b/tests/PHPExif/Exception/NoExifDataExceptionTest.php new file mode 100644 index 0000000..868e41f --- /dev/null +++ b/tests/PHPExif/Exception/NoExifDataExceptionTest.php @@ -0,0 +1,22 @@ + + */ +class NoExifDataExceptionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @group exception + * @covers \PHPExif\Exception\NoExifDataException::fromFile + */ + public function testFromFileReturnsInstance() + { + $instance = NoExifDataException::fromFile('foo'); + + $this->assertInstanceOf( + '\\PHPExif\\Exception\\NoExifDataException', + $instance + ); + } +} From 86937cd9be88aa5a8993ae5bc77576d4da714ebc Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 20:06:38 +0100 Subject: [PATCH 08/51] phpunit config had wrong path in whitelist Signed-off-by: Tom Van Herreweghe --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e7811f7..76995b9 100755 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -11,7 +11,7 @@ - ./lib + ./src *Interface.php From 7becf9eb2d9fd10bb5d09b32927427743211f5b5 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 20:07:04 +0100 Subject: [PATCH 09/51] Platform requirements changed to PHP:~5.3 Signed-off-by: Tom Van Herreweghe --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 23b0154..18776bf 100755 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ ], "keywords": ["EXIF", "IPTC", "jpeg", "tiff", "exiftool"], "require": { - "php": ">=5.3.0" + "php": "~5.3" }, "require-dev": { "phpmd/phpmd": "~2.2.0", From 898a51fe165c6cdd08f380ee09c1db84a4195e08 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 21:50:15 +0100 Subject: [PATCH 10/51] Metadata class which should be the entry point to EXIF data & IPTC data etc. Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/Metadata.php | 79 ++++++++++++++++++++++++++ src/PHPExif/Data/MetadataInterface.php | 55 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/PHPExif/Data/Metadata.php create mode 100644 src/PHPExif/Data/MetadataInterface.php diff --git a/src/PHPExif/Data/Metadata.php b/src/PHPExif/Data/Metadata.php new file mode 100644 index 0000000..dcf39ac --- /dev/null +++ b/src/PHPExif/Data/Metadata.php @@ -0,0 +1,79 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +/** + * Metadata class + * + * Container for Metadata of an image + * + * @category PHPExif + * @package Exif + */ +final class Metadata implements MetadataInterface +{ + /** + * @var ExifInterface + */ + private $exif; + + /** + * @var IptcInterface + */ + private $iptc; + + /** + * {@inheritDoc} + */ + public function withExif(ExifInterface $exif) + { + $new = clone $this; + $new->exif = $exif; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function withIptc(IptcInterface $iptc) + { + $new = clone $this; + $new->iptc = $iptc; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function getExif() + { + if (null === $this->exif) { + $this->exif = new Exif(array()); + } + + return $this->exif; + } + + /** + * {@inheritDoc} + */ + public function getIptc() + { + if (null === $this->iptc) { + $this->iptc = new Iptc(array()); + } + + return $this->iptc; + } +} diff --git a/src/PHPExif/Data/MetadataInterface.php b/src/PHPExif/Data/MetadataInterface.php new file mode 100644 index 0000000..dd4c90c --- /dev/null +++ b/src/PHPExif/Data/MetadataInterface.php @@ -0,0 +1,55 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +/** + * MetadataInterface + * + * Public API for accessing the metadata of a file + * + * @category PHPExif + * @package Exif + */ +interface MetadataInterface +{ + /** + * Returns new instance with given EXIF data + * + * @param ExifInterface $exif + * + * @return MetadataInterface + */ + public function withExif(ExifInterface $exif); + + /** + * Returns new instance with given IPTC data + * + * @param IptcInterface $iptc + * + * @return MetadataInterface + */ + public function withIptc(IptcInterface $iptc); + + /** + * Returns the available EXIF data + * + * @return ExifInterface + */ + public function getExif(); + + /** + * Returns the available IPTC data + * + * @return IptcInterface + */ + public function getIptc(); +} From f3177611ad43b5c84453ef14e80f217ea8bb764f Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 21:51:02 +0100 Subject: [PATCH 11/51] Made IptcInterface more readable Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/IptcInterface.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/PHPExif/Data/IptcInterface.php b/src/PHPExif/Data/IptcInterface.php index dbf2f8d..3c1cf65 100644 --- a/src/PHPExif/Data/IptcInterface.php +++ b/src/PHPExif/Data/IptcInterface.php @@ -25,6 +25,7 @@ interface IptcInterface * Array represenation of current instance * * @param boolean $withEmpty + * * @return array */ public function toArray($withEmpty = true); @@ -40,6 +41,7 @@ public function getCaption(); * Returns new instance with updated caption * * @param string $caption + * * @return IptcInterface */ public function withCaption($caption); @@ -55,6 +57,7 @@ public function getCopyright(); * Returns new instance with updated copyright * * @param string $copyright + * * @return IptcInterface */ public function withCopyright($copyright); @@ -70,6 +73,7 @@ public function getCredit(); * Returns new instance with updated credit * * @param string $credit + * * @return IptcInterface */ public function withCredit($credit); @@ -85,6 +89,7 @@ public function getHeadline(); * Returns new instance with updated headline * * @param string $headline + * * @return IptcInterface */ public function withHeadline($headline); @@ -100,6 +105,7 @@ public function getJobtitle(); * Returns new instance with updated jobtitle * * @param string $jobtitle + * * @return IptcInterface */ public function withJobtitle($jobitle); @@ -115,6 +121,7 @@ public function getKeywords(); * Returns new instance with updated keywords * * @param string $keywords + * * @return IptcInterface */ public function withKeywords(array $keywords); @@ -130,6 +137,7 @@ public function getSource(); * Returns new instance with updated source * * @param string $source + * * @return IptcInterface */ public function withSource($source); @@ -145,6 +153,7 @@ public function getTitle(); * Returns new instance with updated title * * @param string $title + * * @return IptcInterface */ public function withTitle($title); From 6dfbcb38fb80e88f30e4eceab6071034c033da5f Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 17 Feb 2016 21:53:08 +0100 Subject: [PATCH 12/51] Readability cleanup; Other cleanup; Changed ::read into ::getMetadataFromFile Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/MapperInterface.php | 16 +-- .../Adapter/Native/Reader/Configuration.php | 84 ++-------------- src/PHPExif/Adapter/Native/Reader/Mapper.php | 2 - src/PHPExif/Adapter/Native/Reader/Reader.php | 98 +++++++++++-------- src/PHPExif/Adapter/ReaderInterface.php | 9 +- src/PHPExif/Exception/NoExifDataException.php | 1 + .../Exception/UnknownAdapterTypeException.php | 2 + src/PHPExif/Reader.php | 4 +- src/PHPExif/ReaderInterface.php | 10 +- tests/PHPExif/ReaderTest.php | 6 +- 10 files changed, 89 insertions(+), 143 deletions(-) diff --git a/src/PHPExif/Adapter/MapperInterface.php b/src/PHPExif/Adapter/MapperInterface.php index ce624f9..3552532 100644 --- a/src/PHPExif/Adapter/MapperInterface.php +++ b/src/PHPExif/Adapter/MapperInterface.php @@ -12,7 +12,7 @@ namespace PHPExif\Adapter; -use PHPExif\Data\ExifInterface; +use PHPExif\Data\MetadataInterface; /** * MapperInterface @@ -27,19 +27,11 @@ interface MapperInterface { /** * Maps the array of raw source data to the correct - * fields for the \PHPExif\Exif class + * value objects * * @param array $data - * @return ExifInterface - */ - public function map(array $data); - - /** - * Maps the data of given Exif object - * to an array of raw data * - * @param ExifInterface $exif - * @return array + * @return MetadataInterface */ - public function serialize(ExifInterface $exif); + public function map(array $data); } diff --git a/src/PHPExif/Adapter/Native/Reader/Configuration.php b/src/PHPExif/Adapter/Native/Reader/Configuration.php index 2cac869..b18325f 100644 --- a/src/PHPExif/Adapter/Native/Reader/Configuration.php +++ b/src/PHPExif/Adapter/Native/Reader/Configuration.php @@ -26,35 +26,10 @@ final class Configuration const SECTIONS_AS_ARRAYS = true; const SECTIONS_FLAT = false; - const SECTION_FILE = 'FILE'; - const SECTION_COMPUTED = 'COMPUTED'; - const SECTION_IFD0 = 'IFD0'; - const SECTION_THUMBNAIL = 'THUMBNAIL'; - const SECTION_COMMENT = 'COMMENT'; - const SECTION_EXIF = 'EXIF'; - const SECTION_ALL = 'ANY_TAG'; - const SECTION_IPTC = 'IPTC'; + const SECTIONS = 'ANY_TAG'; - /** - * List of EXIF sections - * - * @var array - */ - private $requiredSections = array(); - - /** - * Include the thumbnail in the EXIF data? - * - * @var boolean - */ - public $includeThumbnail = self::NO_THUMBNAIL; - - /** - * Parse the sections as arrays? - * - * @var boolean - */ - public $sectionsAsArrays = self::SECTIONS_FLAT; + const IPTC_EXIF_ONLY = false; + const IPTC_ADD_RAW = true; /** * Classname of the Mapper to use when mapping raw data @@ -65,55 +40,10 @@ final class Configuration public $mapperClass = '\\PHPExif\\Adapter\\Native\\Mapper'; /** - * Getter for the EXIF sections - * - * @return array - */ - public function getRequiredSections() - { - return $this->requiredSections; - } - - /** - * Returns the required EXIF sections as - * a comma-separated string - * - * @return string - */ - public function getRequiredSectionsAsString() - { - if (empty($this->requiredSections)) { - return null; - } - - return implode(',', $this->requiredSections); - } - - /** - * Setter for the EXIF sections + * Parse IPTC data from binary data and add it to the + * data read from Exif? * - * @param array $sections List of EXIF sections - * @return Configuration + * @var bool */ - public function setRequiredSections(array $sections) - { - $this->requiredSections = $sections; - - return $this; - } - - /** - * Adds an EXIF section to the list - * - * @param string $section - * @return Configuration - */ - public function addRequiredSection($section) - { - if (!in_array($section, $this->requiredSections)) { - array_push($this->requiredSections, $section); - } - - return $this; - } + public $parseRawIptcData = self::IPTC_ADD_RAW; } diff --git a/src/PHPExif/Adapter/Native/Reader/Mapper.php b/src/PHPExif/Adapter/Native/Reader/Mapper.php index 9ea6f54..9876022 100644 --- a/src/PHPExif/Adapter/Native/Reader/Mapper.php +++ b/src/PHPExif/Adapter/Native/Reader/Mapper.php @@ -54,7 +54,6 @@ final class Mapper implements MapperInterface const XRESOLUTION = 'XResolution'; const YRESOLUTION = 'YResolution'; - const SECTION_ALL = 'ANY_TAG'; const SECTION_COMMENT = 'COMMENT'; const SECTION_COMPUTED = 'COMPUTED'; const SECTION_EXIF = 'EXIF'; @@ -69,7 +68,6 @@ final class Mapper implements MapperInterface * @var array */ private $sections = array( - self::SECTION_ALL, self::SECTION_COMMENT, self::SECTION_COMPUTED, self::SECTION_EXIF, diff --git a/src/PHPExif/Adapter/Native/Reader/Reader.php b/src/PHPExif/Adapter/Native/Reader/Reader.php index bfc2caf..1af147e 100644 --- a/src/PHPExif/Adapter/Native/Reader/Reader.php +++ b/src/PHPExif/Adapter/Native/Reader/Reader.php @@ -14,9 +14,6 @@ use PHPExif\Adapter\MapperInterface; use PHPExif\Adapter\ReaderInterface; -use PHPExif\Data\Exif; -use PHPExif\Data\Iptc; -use PHPExif\Data\IptcInterface; use PHPExif\Exception\NoExifDataException; use PHPExif\Exception\UnknownAdapterTypeException; @@ -33,6 +30,11 @@ final class Reader implements ReaderInterface */ private $configuration; + /** + * @var MapperInterface + */ + private $mapper; + /** * @param Configuration $configuration */ @@ -49,8 +51,9 @@ public function __construct(Configuration $configuration) */ public static function withDefaults() { - $configuration = new Configuration(); - $instance = new Reader($configuration); + $instance = new Reader( + new Configuration + ); return $instance; } @@ -58,13 +61,31 @@ public static function withDefaults() /** * Returns an instance of the configured mapper class * - * @return MapperInterface * @throws UnknownAdapterTypeException + * + * @return MapperInterface */ public function getMapper() { - $mapper = new $this->configuration->mapperClass; + if (null !== $this->mapper) { + return $this->mapper; + } + + $this-> mapper = $this->initializeMapper(); + + return $this->mapper; + } + /** + * Creates a new MapperInterface instance + * from given Configuration + * + * @return MapperInterface + */ + private function initializeMapper() + { + $mapper = new $this->configuration->mapperClass; + if (!$mapper instanceof MapperInterface) { throw UnknownAdapterTypeException::noInterface( $this->configuration->mapperClass, @@ -77,62 +98,59 @@ public function getMapper() /** * {@inheritDoc} + * * @throws NoExifDataException */ - public function read($filePath) + public function getMetadataFromFile($filePath) { $data = @exif_read_data( $filePath, - $this->configuration->getRequiredSectionsAsString(), - $this->configuration->sectionsAsArrays, - $this->configuration->includeThumbnail + Configuration::SECTIONS, + Configuration::SECTIONS_FLAT, + Configuration::NO_THUMBNAIL ); if (false === $data) { throw NoExifDataException::fromFile($filePath); } - $iptc = $this->getIptcData($file); - $data = array_merge( - $data, - array( - Configuration::SECTION_IPTC => $iptc->toArray(), - ) - ); + $this->augmentDataWithIptcRawData($data); // map the data: $mapper = $this->getMapper(); - $exif = $mapper->map($data); + $readerResult = $mapper->map($data); - return $exif; + return $readerResult; } /** - * Returns an array of IPTC data + * Adds data from iptcparse to the original raw EXIF data + * + * @param array $data * - * @param string $file The file to read the IPTC data from - * @return IptcInterface + * @return void */ - private function getIptcData($file) + private function augmentDataWithIptcRawData(array &$data) { + if (!$this->configuration->parseRawIptcData) { + return; + } + getimagesize($file, $info); - $arrData = array(); - if (isset($info['APP13'])) { - $iptc = iptcparse($info['APP13']); - - foreach (Iptc::$iptcMapping as $name => $field) { - if (!isset($iptc[$field])) { - continue; - } - - $value = $iptc[$field]; - if (count($value) === 1) { - $value = reset($value); - } - $arrData[$name] = $value; - } + if (!array_key_exists('APP13', $info)) { + return; + } + $iptcRawData = iptcparse($info['APP13']); + + // UTF8 + if (isset($iptc["1#090"]) && $iptc["1#090"][0] == "\x1B%G") { + $iptcRawData = array_map('utf8_encode', $iptcRawData); } - return new Iptc($arrData); + // Merge with original raw Exif data + $data = array_merge( + $data, + $iptcRawData + ); } } diff --git a/src/PHPExif/Adapter/ReaderInterface.php b/src/PHPExif/Adapter/ReaderInterface.php index a52d9c8..2d5fa67 100644 --- a/src/PHPExif/Adapter/ReaderInterface.php +++ b/src/PHPExif/Adapter/ReaderInterface.php @@ -11,7 +11,7 @@ namespace PHPExif\Adapter; -use PHPExif\Data\ExifInterface; +use PHPExif\Data\MetadataInterface; /** * ReaderInterface @@ -24,10 +24,11 @@ interface ReaderInterface { /** - * Read the EXIF metadata of given file + * Read the available metadata of given file * * @param string $filePath - * @return ExifInterface + * + * @return MetadataInterface */ - public function read($filePath); + public function getMetadataFromFile($filePath); } diff --git a/src/PHPExif/Exception/NoExifDataException.php b/src/PHPExif/Exception/NoExifDataException.php index 14b94a1..25f2dd3 100644 --- a/src/PHPExif/Exception/NoExifDataException.php +++ b/src/PHPExif/Exception/NoExifDataException.php @@ -23,6 +23,7 @@ class NoExifDataException extends \Exception * Could not read EXIF data from given path * * @param string $path + * * @return NoExifDataException */ public static function fromFile($path) diff --git a/src/PHPExif/Exception/UnknownAdapterTypeException.php b/src/PHPExif/Exception/UnknownAdapterTypeException.php index decc1ef..59fb2fb 100644 --- a/src/PHPExif/Exception/UnknownAdapterTypeException.php +++ b/src/PHPExif/Exception/UnknownAdapterTypeException.php @@ -23,6 +23,7 @@ class UnknownAdapterTypeException extends \Exception * No adapter set in the reader * * @param string $type + * * @return UnknownAdapterTypeException */ public static function forType($type) @@ -40,6 +41,7 @@ public static function forType($type) * * @param string $classname * @param string $interfaceName + * * @return UnknownAdapterTypeException */ public static function noInterface($classname, $interfaceName) diff --git a/src/PHPExif/Reader.php b/src/PHPExif/Reader.php index 206cf8f..642a9ff 100644 --- a/src/PHPExif/Reader.php +++ b/src/PHPExif/Reader.php @@ -76,8 +76,8 @@ public static function factory($type) /** * {@inheritDoc} */ - public function read($file) + public function getMetadataFromFile($file) { - return $this->getAdapter()->read($file); + return $this->getAdapter()->getMetadataFromFile($file); } } diff --git a/src/PHPExif/ReaderInterface.php b/src/PHPExif/ReaderInterface.php index c82e4fb..13a7b95 100644 --- a/src/PHPExif/ReaderInterface.php +++ b/src/PHPExif/ReaderInterface.php @@ -11,6 +11,7 @@ namespace PHPExif; +use PHPExif\Data\MetadataInterface; use PHPExif\Exception\UnknownAdapterTypeException; /** @@ -37,8 +38,10 @@ public function getAdapter(); * Factory for the reader * * @param string $type - * @return ReaderInterface + * * @throws UnknownAdapterTypeException When given type is invalid + * + * @return ReaderInterface */ public static function factory($type); @@ -46,7 +49,8 @@ public static function factory($type); * Reads & parses the EXIF data from given file * * @param string $file - * @return \PHPExif\Data\Exif + * + * @return MetadataInterface */ - public function read($file); + public function getMetadataFromFile($file); } diff --git a/tests/PHPExif/ReaderTest.php b/tests/PHPExif/ReaderTest.php index bceeede..e406997 100644 --- a/tests/PHPExif/ReaderTest.php +++ b/tests/PHPExif/ReaderTest.php @@ -68,7 +68,7 @@ public function testFactoryForNativeReturnsInstanceWithCorrectAdapter() /** * @group reader - * @covers \PHPExif\Reader::read + * @covers \PHPExif\Reader::getMetadataFromFile */ public function testReadForwardsToAdapter() { @@ -76,12 +76,12 @@ public function testReadForwardsToAdapter() $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') ->getMock(); $adapter->expects($this->once()) - ->method('read') + ->method('getMetadataFromFile') ->with( $this->equalTo($file) ); $reader = new \PHPExif\Reader($adapter); - $reader->read($file); + $reader->getMetadataFromFile($file); } } From aad8cda5efacc815e196a581189f27f305642ef4 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 25 Feb 2016 22:16:58 +0100 Subject: [PATCH 13/51] Added PHP codesniffer as dev dependency Signed-off-by: Tom Van Herreweghe --- composer.json | 1 + composer.lock | 331 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 230 insertions(+), 102 deletions(-) diff --git a/composer.json b/composer.json index 18776bf..4ee5d8b 100755 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ }, "require-dev": { "phpmd/phpmd": "~2.2.0", + "squizlabs/php_codesniffer": "~2.0", "phpro/grumphp": "~0.1", "phpunit/phpunit": "~4.5.0", "satooshi/php-coveralls": "~0.6" diff --git a/composer.lock b/composer.lock index 2129860..2d75a54 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "a21b65b95d8bbe995e9e27fb805ed85d", - "content-hash": "7cfc59e9aed93dbd6468e13bc1896af9", + "hash": "8e6a21a69c173002f8fe63d86f2f6dac", + "content-hash": "ee75718f2df39afae1d732e9b5cc4325", "packages": [], "packages-dev": [ { @@ -188,12 +188,12 @@ "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "74fc3909170d66f3e93719ae025b79faea1f49f5" + "reference": "739b9c8378c462943c42fee5353453ab4164ed8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/74fc3909170d66f3e93719ae025b79faea1f49f5", - "reference": "74fc3909170d66f3e93719ae025b79faea1f49f5", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/739b9c8378c462943c42fee5353453ab4164ed8e", + "reference": "739b9c8378c462943c42fee5353453ab4164ed8e", "shasum": "" }, "require": { @@ -209,7 +209,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "6.2-dev" } }, "autoload": { @@ -242,7 +242,7 @@ "rest", "web service" ], - "time": "2015-12-29 21:28:50" + "time": "2016-02-17 21:09:10" }, { "name": "guzzlehttp/promises", @@ -250,12 +250,12 @@ "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea" + "reference": "dc03e97371e37172ff94547980f898659de76ffc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b1e1c0d55f8083c71eda2c28c12a228d708294ea", - "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea", + "url": "https://api.github.com/repos/guzzle/promises/zipball/dc03e97371e37172ff94547980f898659de76ffc", + "reference": "dc03e97371e37172ff94547980f898659de76ffc", "shasum": "" }, "require": { @@ -293,20 +293,20 @@ "keywords": [ "promise" ], - "time": "2015-10-15 22:28:00" + "time": "2016-02-23 21:19:12" }, { "name": "guzzlehttp/psr7", - "version": "1.2.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982" + "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982", - "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", + "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", "shasum": "" }, "require": { @@ -351,30 +351,30 @@ "stream", "uri" ], - "time": "2015-11-03 01:34:55" + "time": "2016-02-18 21:54:00" }, { "name": "pdepend/pdepend", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "d3ae0d084d526cdc6c3f1b858fb7148de77b41c5" + "reference": "9d816dfa565b9c47685057761acaf432c9e8066a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/d3ae0d084d526cdc6c3f1b858fb7148de77b41c5", - "reference": "d3ae0d084d526cdc6c3f1b858fb7148de77b41c5", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/9d816dfa565b9c47685057761acaf432c9e8066a", + "reference": "9d816dfa565b9c47685057761acaf432c9e8066a", "shasum": "" }, "require": { "php": ">=5.3.7", - "symfony/config": "^2.3.0", - "symfony/dependency-injection": "^2.3.0", - "symfony/filesystem": "^2.3.0" + "symfony/config": "^2.3.0|^3", + "symfony/dependency-injection": "^2.3.0|^3", + "symfony/filesystem": "^2.3.0|^3" }, "require-dev": { - "phpunit/phpunit": "^4.0.0,<4.8", + "phpunit/phpunit": "^4.4.0,<4.8", "squizlabs/php_codesniffer": "^2.0.0" }, "bin": [ @@ -382,8 +382,8 @@ ], "type": "library", "autoload": { - "psr-0": { - "PDepend\\": "src/main/php/" + "psr-4": { + "PDepend\\": "src/main/php/PDepend" } }, "notification-url": "https://packagist.org/downloads/", @@ -391,7 +391,7 @@ "BSD-3-Clause" ], "description": "Official version of pdepend to be handled with Composer", - "time": "2015-10-16 08:49:58" + "time": "2016-02-23 08:20:26" }, { "name": "phpdocumentor/reflection-docblock", @@ -506,16 +506,16 @@ }, { "name": "phpro/grumphp", - "version": "v0.7.0", + "version": "v0.7.2", "source": { "type": "git", "url": "https://github.com/phpro/grumphp.git", - "reference": "6d675b47011f0bcf1cb4ec6644b731ed5a416714" + "reference": "6ddca8723c622eecf3e9c96c6b84c587eda7cf0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpro/grumphp/zipball/6d675b47011f0bcf1cb4ec6644b731ed5a416714", - "reference": "6d675b47011f0bcf1cb4ec6644b731ed5a416714", + "url": "https://api.github.com/repos/phpro/grumphp/zipball/6ddca8723c622eecf3e9c96c6b84c587eda7cf0c", + "reference": "6ddca8723c622eecf3e9c96c6b84c587eda7cf0c", "shasum": "" }, "require": { @@ -523,6 +523,7 @@ "doctrine/collections": "~1.2", "gitonomy/gitlib": "~0.1.7", "php": ">=5.3.6", + "seld/jsonlint": "~1.1", "symfony/config": "~2.4|~3.0", "symfony/console": "~2.6|~3.0", "symfony/dependency-injection": "~2.4|~3.0", @@ -537,7 +538,9 @@ "composer/composer": "^1.0-alpha11", "fabpot/php-cs-fixer": "~1.0", "phpspec/phpspec": "~2.4", + "phpunit/phpunit": "^4.8", "roave/security-advisories": "dev-master@dev", + "sensiolabs/security-checker": "^3.0", "squizlabs/php_codesniffer": "~2.3" }, "suggest": { @@ -547,6 +550,7 @@ "phpspec/phpspec": "Lets GrumPHP spec your code.", "phpunit/phpunit": "Lets GrumPHP run your unit tests.", "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues.", + "sensiolabs/security-checker": "Lets GrumPHP be sure that there are no known security issues.", "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code." }, "bin": [ @@ -576,7 +580,7 @@ } ], "description": "A composer plugin that enables source code quality checks.", - "time": "2015-12-11 12:13:59" + "time": "2016-02-03 15:54:43" }, { "name": "phpspec/prophecy", @@ -584,12 +588,12 @@ "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "e55e3e32a870bd4f05425fa4f717b52bd40e5659" + "reference": "b02221e42163be673f9b44a0bc92a8b4907a7c6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e55e3e32a870bd4f05425fa4f717b52bd40e5659", - "reference": "e55e3e32a870bd4f05425fa4f717b52bd40e5659", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b02221e42163be673f9b44a0bc92a8b4907a7c6d", + "reference": "b02221e42163be673f9b44a0bc92a8b4907a7c6d", "shasum": "" }, "require": { @@ -605,7 +609,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -638,7 +642,7 @@ "spy", "stub" ], - "time": "2015-12-28 13:26:33" + "time": "2016-02-21 17:41:21" }, { "name": "phpunit/php-code-coverage", @@ -1122,10 +1126,10 @@ "guzzlehttp/guzzle": "^6.0", "php": ">=5.5", "psr/log": "^1.0", - "symfony/config": "^2.4|^3.0", + "symfony/config": "^2.1|^3.0", "symfony/console": "^2.1|^3.0", - "symfony/stopwatch": "^2.2|^3.0", - "symfony/yaml": "^2.1|^3.0" + "symfony/stopwatch": "^2.0|^3.0", + "symfony/yaml": "^2.0|^3.0" }, "require-dev": { "apigen/apigen": "^2.8", @@ -1466,12 +1470,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", + "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", "shasum": "" }, "require": { @@ -1511,7 +1515,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2016-01-28 05:39:29" }, { "name": "sebastian/version", @@ -1548,28 +1552,154 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2015-06-21 13:59:46" }, + { + "name": "seld/jsonlint", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "66834d3e3566bb5798db7294619388786ae99394" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/66834d3e3566bb5798db7294619388786ae99394", + "reference": "66834d3e3566bb5798db7294619388786ae99394", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "time": "2015-11-21 02:21:41" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "825c050244393fc4231e5bf97f7569c2831795aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/825c050244393fc4231e5bf97f7569c2831795aa", + "reference": "825c050244393fc4231e5bf97f7569c2831795aa", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2016-02-22 03:53:15" + }, { "name": "symfony/config", - "version": "2.8.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74" + "reference": "f1f7ccf4c17454cf14f43178624c4890cba788d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", - "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", + "url": "https://api.github.com/repos/symfony/config/zipball/f1f7ccf4c17454cf14f43178624c4890cba788d8", + "reference": "f1f7ccf4c17454cf14f43178624c4890cba788d8", "shasum": "" }, "require": { - "php": ">=5.3.9", - "symfony/filesystem": "~2.3|~3.0.0" + "php": ">=5.5.9", + "symfony/filesystem": "~2.8|~3.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1596,7 +1726,7 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-01-03 15:33:41" + "time": "2016-02-23 16:17:05" }, { "name": "symfony/console", @@ -1604,12 +1734,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0360a690902c60a0aeda2b4da0bcf1098ee849ce" + "reference": "50c745b4f1047632f7e46a70ba010789c4a9e385" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0360a690902c60a0aeda2b4da0bcf1098ee849ce", - "reference": "0360a690902c60a0aeda2b4da0bcf1098ee849ce", + "url": "https://api.github.com/repos/symfony/console/zipball/50c745b4f1047632f7e46a70ba010789c4a9e385", + "reference": "50c745b4f1047632f7e46a70ba010789c4a9e385", "shasum": "" }, "require": { @@ -1656,32 +1786,29 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-01-15 09:32:41" + "time": "2016-02-23 16:17:05" }, { "name": "symfony/dependency-injection", - "version": "2.8.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "ba94a914e244e0d05f0aaef460d5558d5541d2b1" + "reference": "7cdf5f9ca7d90b768189c759f338b0cf4ca05e76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ba94a914e244e0d05f0aaef460d5558d5541d2b1", - "reference": "ba94a914e244e0d05f0aaef460d5558d5541d2b1", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/7cdf5f9ca7d90b768189c759f338b0cf4ca05e76", + "reference": "7cdf5f9ca7d90b768189c759f338b0cf4ca05e76", "shasum": "" }, "require": { - "php": ">=5.3.9" - }, - "conflict": { - "symfony/expression-language": "<2.6" + "php": ">=5.5.9" }, "require-dev": { - "symfony/config": "~2.2|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/yaml": "~2.1|~3.0.0" + "symfony/config": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" }, "suggest": { "symfony/config": "", @@ -1691,7 +1818,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1718,7 +1845,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-01-12 17:46:01" + "time": "2016-02-22 01:22:58" }, { "name": "symfony/event-dispatcher", @@ -1726,12 +1853,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c021a1c4f1d0a7594542c3d1f231d71677ab4ea5" + "reference": "9d7930726e060b0c45ae10022a4cb307e502500b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c021a1c4f1d0a7594542c3d1f231d71677ab4ea5", - "reference": "c021a1c4f1d0a7594542c3d1f231d71677ab4ea5", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9d7930726e060b0c45ae10022a4cb307e502500b", + "reference": "9d7930726e060b0c45ae10022a4cb307e502500b", "shasum": "" }, "require": { @@ -1778,29 +1905,29 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-01-14 07:58:06" + "time": "2016-02-04 12:57:09" }, { "name": "symfony/filesystem", - "version": "2.8.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c" + "reference": "c8a0b857efc7c19b087129a7d7555f866d61b557" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", - "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c8a0b857efc7c19b087129a7d7555f866d61b557", + "reference": "c8a0b857efc7c19b087129a7d7555f866d61b557", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1827,7 +1954,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-02-23 16:17:05" }, { "name": "symfony/finder", @@ -1835,12 +1962,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "45571dd5f5b512a650949f089baf07edc5575b53" + "reference": "43a0bde21f9f390131917b6202eb02b3fea1f799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/45571dd5f5b512a650949f089baf07edc5575b53", - "reference": "45571dd5f5b512a650949f089baf07edc5575b53", + "url": "https://api.github.com/repos/symfony/finder/zipball/43a0bde21f9f390131917b6202eb02b3fea1f799", + "reference": "43a0bde21f9f390131917b6202eb02b3fea1f799", "shasum": "" }, "require": { @@ -1876,7 +2003,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-01-15 09:32:41" + "time": "2016-02-04 12:57:09" }, { "name": "symfony/options-resolver", @@ -1884,12 +2011,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "5d3eea990b8e1799e305ab32f1369ff89b3c2b72" + "reference": "0d15b40701e1778bdbc206c8545ad423402021c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d3eea990b8e1799e305ab32f1369ff89b3c2b72", - "reference": "5d3eea990b8e1799e305ab32f1369ff89b3c2b72", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0d15b40701e1778bdbc206c8545ad423402021c4", + "reference": "0d15b40701e1778bdbc206c8545ad423402021c4", "shasum": "" }, "require": { @@ -1930,7 +2057,7 @@ "configuration", "options" ], - "time": "2016-01-03 15:35:40" + "time": "2016-01-21 10:01:50" }, { "name": "symfony/polyfill-mbstring", @@ -1938,12 +2065,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d7f01c96a4dde264682cf36c28e62086c77a09d4" + "reference": "1289d16209491b584839022f29257ad859b8532d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d7f01c96a4dde264682cf36c28e62086c77a09d4", - "reference": "d7f01c96a4dde264682cf36c28e62086c77a09d4", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", + "reference": "1289d16209491b584839022f29257ad859b8532d", "shasum": "" }, "require": { @@ -1955,7 +2082,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } }, "autoload": { @@ -1989,7 +2116,7 @@ "portable", "shim" ], - "time": "2016-01-13 07:16:33" + "time": "2016-01-20 09:13:37" }, { "name": "symfony/process", @@ -1997,12 +2124,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1cba8f04eb0a9e38184a8003e927a5fb2d62158a" + "reference": "650a91315648fe433824e454b2c7107926f9876b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1cba8f04eb0a9e38184a8003e927a5fb2d62158a", - "reference": "1cba8f04eb0a9e38184a8003e927a5fb2d62158a", + "url": "https://api.github.com/repos/symfony/process/zipball/650a91315648fe433824e454b2c7107926f9876b", + "reference": "650a91315648fe433824e454b2c7107926f9876b", "shasum": "" }, "require": { @@ -2038,7 +2165,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-01-06 10:01:46" + "time": "2016-02-04 12:57:09" }, { "name": "symfony/stopwatch", @@ -2095,12 +2222,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8" + "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/34c8a4b51e751e7ea869b8262f883d008a2b81b8", - "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", + "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", "shasum": "" }, "require": { @@ -2136,7 +2263,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-02-23 07:41:20" } ], "aliases": [], @@ -2145,7 +2272,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.3.0" + "php": "~5.3" }, "platform-dev": [] } From 34b7f2e767e34a237c40125011eceb97ce8c3b80 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 25 Feb 2016 22:19:00 +0100 Subject: [PATCH 14/51] Removed grumPHP Signed-off-by: Tom Van Herreweghe --- composer.json | 1 - composer.lock | 82 ++------------------------------------------------- grumphp.yml | 21 ------------- 3 files changed, 2 insertions(+), 102 deletions(-) delete mode 100644 grumphp.yml diff --git a/composer.json b/composer.json index 4ee5d8b..63b9548 100755 --- a/composer.json +++ b/composer.json @@ -17,7 +17,6 @@ "require-dev": { "phpmd/phpmd": "~2.2.0", "squizlabs/php_codesniffer": "~2.0", - "phpro/grumphp": "~0.1", "phpunit/phpunit": "~4.5.0", "satooshi/php-coveralls": "~0.6" }, diff --git a/composer.lock b/composer.lock index 2d75a54..29cd0b5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "8e6a21a69c173002f8fe63d86f2f6dac", - "content-hash": "ee75718f2df39afae1d732e9b5cc4325", + "hash": "e2c68dea9211298714ff36e4e05a9457", + "content-hash": "a10f7df39b899fc8f73d61c82a9026e1", "packages": [], "packages-dev": [ { @@ -504,84 +504,6 @@ ], "time": "2015-05-27 18:16:57" }, - { - "name": "phpro/grumphp", - "version": "v0.7.2", - "source": { - "type": "git", - "url": "https://github.com/phpro/grumphp.git", - "reference": "6ddca8723c622eecf3e9c96c6b84c587eda7cf0c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpro/grumphp/zipball/6ddca8723c622eecf3e9c96c6b84c587eda7cf0c", - "reference": "6ddca8723c622eecf3e9c96c6b84c587eda7cf0c", - "shasum": "" - }, - "require": { - "composer-plugin-api": "~1.0", - "doctrine/collections": "~1.2", - "gitonomy/gitlib": "~0.1.7", - "php": ">=5.3.6", - "seld/jsonlint": "~1.1", - "symfony/config": "~2.4|~3.0", - "symfony/console": "~2.6|~3.0", - "symfony/dependency-injection": "~2.4|~3.0", - "symfony/event-dispatcher": "~2.5|~3.0", - "symfony/filesystem": "~2.4|~3.0", - "symfony/finder": "~2.4|~3.0", - "symfony/options-resolver": "~2.6|~3.0", - "symfony/process": "~2.4|~3.0", - "symfony/yaml": "~2.4|~3.0" - }, - "require-dev": { - "composer/composer": "^1.0-alpha11", - "fabpot/php-cs-fixer": "~1.0", - "phpspec/phpspec": "~2.4", - "phpunit/phpunit": "^4.8", - "roave/security-advisories": "dev-master@dev", - "sensiolabs/security-checker": "^3.0", - "squizlabs/php_codesniffer": "~2.3" - }, - "suggest": { - "behat/behat": "Lets GrumPHP validate your project features.", - "codeception/codeception": "Lets GrumPHP run your project's full stack tests", - "fabpot/php-cs-fixer": "Lets GrumPHP automatically fix your codestyle.", - "phpspec/phpspec": "Lets GrumPHP spec your code.", - "phpunit/phpunit": "Lets GrumPHP run your unit tests.", - "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues.", - "sensiolabs/security-checker": "Lets GrumPHP be sure that there are no known security issues.", - "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code." - }, - "bin": [ - "bin/grumphp" - ], - "type": "composer-plugin", - "extra": { - "class": "GrumPHP\\Composer\\GrumPHPPlugin" - }, - "autoload": { - "psr-0": { - "GrumPHP\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Toon Verwerft", - "email": "toon.verwerft@phpro.be" - }, - { - "name": "Alexander Deruwe", - "email": "alexander.deruwe@phpro.be" - } - ], - "description": "A composer plugin that enables source code quality checks.", - "time": "2016-02-03 15:54:43" - }, { "name": "phpspec/prophecy", "version": "dev-master", diff --git a/grumphp.yml b/grumphp.yml deleted file mode 100644 index cb58221..0000000 --- a/grumphp.yml +++ /dev/null @@ -1,21 +0,0 @@ -parameters: - ascii: - failed: ~ - succeeded: ~ - git_dir: . - bin_dir: bin - tasks: - phpcs: - standard: "PSR2" - show_warnings: false - blacklist: - keywords: - - "die(" - - "var_dump(" - - "print_r(" - - "print(" - - "dump(" - - "debug_backtrace(" - - "file_put_contents(" - - "exit;" - - "echo" From 847a20d0a782432ffd4b8edee5556e2501b63363 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 25 Feb 2016 22:19:58 +0100 Subject: [PATCH 15/51] Created Collection interface, abstract implementation & needed exceptions Signed-off-by: Tom Van Herreweghe --- src/PHPExif/AbstractCollection.php | 79 +++++++++++++++++++ src/PHPExif/Collection.php | 57 +++++++++++++ .../ElementAlreadyExistsException.php | 38 +++++++++ .../Collection/ElementNotExistsException.php | 38 +++++++++ .../InvalidElementTypeException.php | 38 +++++++++ 5 files changed, 250 insertions(+) create mode 100644 src/PHPExif/AbstractCollection.php create mode 100644 src/PHPExif/Collection.php create mode 100644 src/PHPExif/Exception/Collection/ElementAlreadyExistsException.php create mode 100644 src/PHPExif/Exception/Collection/ElementNotExistsException.php create mode 100644 src/PHPExif/Exception/Collection/InvalidElementTypeException.php diff --git a/src/PHPExif/AbstractCollection.php b/src/PHPExif/AbstractCollection.php new file mode 100644 index 0000000..c5da830 --- /dev/null +++ b/src/PHPExif/AbstractCollection.php @@ -0,0 +1,79 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif; + +use PHPExif\Exception\Collection\ElementAlreadyExistsException; +use PHPExif\Exception\Collection\ElementNotExistsException; + +/** + * AbstractCollection class + * + * @category PHPExif + * @package Exif + */ +abstract class AbstractCollection implements Collection +{ + /** + * Holds the entries of the collection + * + * @var array + */ + private $elements; + + /** + * Collection constructor + * + * @param array $data + */ + public function __construct(array $elements = array()) + { + $this->elements = array(); + + foreach ($elements as $name => $config) { + $this->add($name, $config); + } + } + + /** + * {@inheritDoc} + */ + public function add($key, $value) + { + if ($this->exists($key)) { + throw ElementAlreadyExistsException::withKey($key); + } + + $this->elements[$key] = $value; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function exists($key) + { + return array_key_exists($key, $this->elements); + } + + /** + * {@inheritDoc} + */ + public function get($key) + { + if (!$this->exists($key)) { + throw ElementNotExistsException::withKey($key); + } + + return $this->element[$key]; + } +} diff --git a/src/PHPExif/Collection.php b/src/PHPExif/Collection.php new file mode 100644 index 0000000..5761f26 --- /dev/null +++ b/src/PHPExif/Collection.php @@ -0,0 +1,57 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif; + +use PHPExif\Exception\Collection\ElementAlreadyExistsException; +use PHPExif\Exception\Collection\ElementNotExistsException; + +/** + * Collection interface + * + * Public API for a collection of elements + * + * @category PHPExif + * @package Exif + */ +interface Collection +{ + /** + * Adds a $value to the elements with key $key + * + * @param string $key + * @param mixed $value + * + * @throws ElementAlreadyExistsException When element with $name is + * already present in the collection + * + * @return Collection + */ + public function add($key, $value); + + /** + * Determines if element with given key exists in the collection + * + * @param string $key + * + * @return bool + */ + public function exists($key); + + /** + * Retrieves element with given key + * + * @throws ElementNotExistsException When requested key is not present + * + * @return mixed + */ + public function get($key); +} diff --git a/src/PHPExif/Exception/Collection/ElementAlreadyExistsException.php b/src/PHPExif/Exception/Collection/ElementAlreadyExistsException.php new file mode 100644 index 0000000..066bab0 --- /dev/null +++ b/src/PHPExif/Exception/Collection/ElementAlreadyExistsException.php @@ -0,0 +1,38 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exception + */ + +namespace PHPExif\Exception\Collection; + +/** + * ElementAlreadyExistsException + * + * @category PHPExif + * @package Exception + */ +class ElementAlreadyExistsException extends \Exception +{ + /** + * Returns new instance with message set + * + * @param string $key + * + * @return ElementAlreadyExistsException + */ + public static function withKey($key) + { + return new self( + sprintf( + 'An element with is already present for key "%1$s"', + $key + ) + ); + } +} diff --git a/src/PHPExif/Exception/Collection/ElementNotExistsException.php b/src/PHPExif/Exception/Collection/ElementNotExistsException.php new file mode 100644 index 0000000..2d56bd6 --- /dev/null +++ b/src/PHPExif/Exception/Collection/ElementNotExistsException.php @@ -0,0 +1,38 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exception + */ + +namespace PHPExif\Exception\Collection; + +/** + * ElementNotExistsException + * + * @category PHPExif + * @package Exception + */ +class ElementNotExistsException extends \Exception +{ + /** + * Returns new instance with message set + * + * @param string $key + * + * @return ElementNotExistsException + */ + public static function withKey($key) + { + return new self( + sprintf( + 'No element is present in the collection with key "%1$s"', + $key + ) + ); + } +} diff --git a/src/PHPExif/Exception/Collection/InvalidElementTypeException.php b/src/PHPExif/Exception/Collection/InvalidElementTypeException.php new file mode 100644 index 0000000..f505b0d --- /dev/null +++ b/src/PHPExif/Exception/Collection/InvalidElementTypeException.php @@ -0,0 +1,38 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exception + */ + +namespace PHPExif\Exception\Collection; + +/** + * InvalidElementTypeException + * + * @category PHPExif + * @package Exception + */ +class InvalidElementTypeException extends \Exception +{ + /** + * Returns new instance with message set + * + * @param string $type + * + * @return InvalidElementTypeException + */ + public static function withExpectedType($type) + { + return new self( + sprintf( + 'Only elements of type "%1$s" are allowed in the collection', + $type + ) + ); + } +} From 978d794f11561f307160e488492df5ad7b50cf6c Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 25 Feb 2016 22:22:03 +0100 Subject: [PATCH 16/51] Created PHPExif gateway class & necessary need classes for handling adapters Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/AdapterCollection.php | 97 +++++++++++++++ src/PHPExif/Adapter/AdapterConfig.php | 29 +++++ .../AdapterAlreadyRegisteredException.php | 33 ++++++ .../Adapter/AdapterNotRegisteredException.php | 33 ++++++ src/PHPExif/PHPExif.php | 110 ++++++++++++++++++ src/PHPExif/ReaderCollection.php | 45 +++++++ 6 files changed, 347 insertions(+) create mode 100644 src/PHPExif/Adapter/AdapterCollection.php create mode 100644 src/PHPExif/Adapter/AdapterConfig.php create mode 100644 src/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredException.php create mode 100644 src/PHPExif/Exception/Adapter/AdapterNotRegisteredException.php create mode 100644 src/PHPExif/PHPExif.php create mode 100644 src/PHPExif/ReaderCollection.php diff --git a/src/PHPExif/Adapter/AdapterCollection.php b/src/PHPExif/Adapter/AdapterCollection.php new file mode 100644 index 0000000..f1640ad --- /dev/null +++ b/src/PHPExif/Adapter/AdapterCollection.php @@ -0,0 +1,97 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter; + +use PHPExif\Collection; +use PHPExif\Exception\Adapter\AdapterAlreadyRegisteredException; +use PHPExif\Exception\Collection\InvalidElementTypeException; + +/** + * AdapterCollection + * + * List of adapters with their names & configurations + * + * @category PHPExif + * @package Adapter + */ +final class AdapterCollection implements Collection +{ + /** + * Holds the entries of the collection + * + * @var array + */ + private $elements; + + /** + * AdapterCollection constructor + * + * @param array $data + */ + public function __construct(array $elements = array()) + { + $this->elements = array(); + + foreach ($elements as $name => $config) { + $this->add($name, $config); + } + } + + /** + * {@inheritDoc} + * + * Adds an AdapterConfig to the collection + * + * @throws AdapterAlreadyExistsException When adapter with $name is + * already present in the collection + * @throws InvalidElementTypeException When not a valid AdapterConfig object is added + */ + public function add($key, $value) + { + if ($this->exists($key)) { + throw AdapterAlreadyExistsException::withName($key); + } + + if (!($value instanceof AdapterConfig)) { + throw InvalidElementTypeException::withExpectedType( + 'AdapterConfig' + ); + } + + $this->elements[$key] = $value; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function exists($key) + { + return array_key_exists($key, $this->elements); + } + + /** + * {@inheritDoc} + * + * @throws AdapterNotRegisteredException When requested adapter is not in the collection + */ + public function get($key) + { + if (!$this->exists($key)) { + throw AdapterNotRegistered::withName($key); + } + + return $this->element[$key]; + } +} diff --git a/src/PHPExif/Adapter/AdapterConfig.php b/src/PHPExif/Adapter/AdapterConfig.php new file mode 100644 index 0000000..c738f93 --- /dev/null +++ b/src/PHPExif/Adapter/AdapterConfig.php @@ -0,0 +1,29 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter; + +/** + * AdapterConfig + * + * Defines a public API for a AdapterConfig + * + * @category PHPExif + * @package Adapter + */ +interface AdapterConfig +{ + const READER = 'reader'; + const WRITER = 'writer'; + + public function factory($type); +} diff --git a/src/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredException.php b/src/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredException.php new file mode 100644 index 0000000..79c0d11 --- /dev/null +++ b/src/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredException.php @@ -0,0 +1,33 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exception + */ + +namespace PHPExif\Exception\Adapter; + +use PHPExif\Exception\Collection\ElementAlreadyExistsException; + +/** + * AdapterAlreadyRegisteredException + * + * @category PHPExif + * @package Exception + */ +class AdapterAlreadyRegisteredException extends ElementAlreadyExistsException +{ + public static function withName($name) + { + return new self( + sprintf( + 'An adapter with name "%1$s" is already registered', + $name + ) + ); + } +} diff --git a/src/PHPExif/Exception/Adapter/AdapterNotRegisteredException.php b/src/PHPExif/Exception/Adapter/AdapterNotRegisteredException.php new file mode 100644 index 0000000..d5db3c0 --- /dev/null +++ b/src/PHPExif/Exception/Adapter/AdapterNotRegisteredException.php @@ -0,0 +1,33 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exception + */ + +namespace PHPExif\Exception\Adapter; + +use PHPExif\Exception\Collection\ElementNotExistsException; + +/** + * AdapterNotRegisteredException + * + * @category PHPExif + * @package Exception + */ +class AdapterNotRegisteredException extends ElementNotExistsException +{ + public static function withName($name) + { + return new self( + sprintf( + 'An adapter with name "%1$s" is not registered', + $name + ) + ); + } +} diff --git a/src/PHPExif/PHPExif.php b/src/PHPExif/PHPExif.php new file mode 100644 index 0000000..9909ad2 --- /dev/null +++ b/src/PHPExif/PHPExif.php @@ -0,0 +1,110 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif; + +use PHPExif\Adapter\AdapterCollection; +use PHPExif\Adapter\AdapterConfig; +use PHPExif\Adapter\Native\NativeAdapterConfig; + +/** + * PHPExif class + * + * Acts as the gateway to access a file's EXIF metadata + * + * @category PHPExif + * @package Exif + */ +final class PHPExif +{ + const ADAPTER_NATIVE = 'native'; + + /** + * Holds all configuration for the registered adapters + * + * @var AdapterCollection + */ + private $adapters; + + /** + * Holds all initialized readers + * + * @var ReaderCollection + */ + private $readers; + + /** + * PHPExif constructor + * + * Usage: + * + * // without arguments; Native adapter is always loaded + * $phpexif = new \PHPExif\PHPExif(); + * + * // with arguments to register extra adapter(s) + * $phpexif = new \PHPExif\PHPExif( + * array( + * '' => , + * ) + * ); + * + * $reader = $phpexif->getReader(''); + * $metadata = $reader->getMetadataFromFile(''); + * + * @param array $adapters Optional list of adapters to register + */ + public function __construct(array $adapters = array()) + { + $this->adapters = new AdapterCollection(); + $this->registerAdapter(self::ADAPTER_NATIVE, new NativeAdapterConfig); + + foreach ($adapters as $name => $config) { + $this->registerAdapter($name, $config); + } + } + + /** + * Registers an adapter with its configuration and name + * + * @param name $name + * @param AdapterConfig $config + * + * @return PHPExif + */ + public function registerAdapter($name, AdapterConfig $config) + { + $this->adapters->add($name, $config); + + return $this; + } + + /** + * Initializes & returns Reader of requested adapter + * Once initialized, the reader is cached locally + * + * @param string $name + * + * @return ReaderInterface + */ + public function getReader($name = self::ADAPTER_NATIVE) + { + if ($this->readers->exists($name)) { + return $this->readers->get($name); + } + + $adapterConfig = $this->adapters->get($name); + $reader = $adapterConfig->factory(AdapterConfig::READER); + + $this->readers->add($name, $reader); + + return $reader; + } +} diff --git a/src/PHPExif/ReaderCollection.php b/src/PHPExif/ReaderCollection.php new file mode 100644 index 0000000..1eaa811 --- /dev/null +++ b/src/PHPExif/ReaderCollection.php @@ -0,0 +1,45 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif; + +use PHPExif\Exception\Collection\ElementAlreadyExistsException; +use PHPExif\Exception\Collection\ElementNotExistsException; +use PHPExif\Exception\Collection\InvalidElementTypeException; + +/** + * AbstractCollection class + * + * @category PHPExif + * @package Exif + */ +class ReaderCollection extends AbstractCollection +{ + /** + * {@inheritDoc} + */ + public function add($key, $value) + { + if ($this->exists($key)) { + throw ElementAlreadyExistsException::withKey($key); + } + + if (!($value instanceof ReaderInterface)) { + throw InvalidElementTypeException::withExpectedType( + 'ReaderInterface' + ); + } + + $this->elements[$key] = $value; + + return $this; + } +} From 53d1970318d25f987fed4fa7e53ca152822888b5 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 25 Feb 2016 22:23:41 +0100 Subject: [PATCH 17/51] Restructured Native adapter and refactored some code Signed-off-by: Tom Van Herreweghe --- .../Adapter/Native/{Reader => }/Mapper.php | 2 +- .../Adapter/Native/NativeAdapterConfig.php | 100 ++++++++++++++++++ .../Adapter/Native/{Reader => }/Reader.php | 72 ++++--------- .../Adapter/Native/Reader/Configuration.php | 49 --------- src/PHPExif/Adapter/Native/ReaderConfig.php | 84 +++++++++++++++ src/PHPExif/Adapter/ReaderInterface.php | 16 +++ src/PHPExif/Reader.php | 83 --------------- src/PHPExif/ReaderInterface.php | 56 ---------- tests/PHPExif/ReaderTest.php | 87 --------------- 9 files changed, 224 insertions(+), 325 deletions(-) rename src/PHPExif/Adapter/Native/{Reader => }/Mapper.php (99%) create mode 100644 src/PHPExif/Adapter/Native/NativeAdapterConfig.php rename src/PHPExif/Adapter/Native/{Reader => }/Reader.php (58%) delete mode 100644 src/PHPExif/Adapter/Native/Reader/Configuration.php create mode 100644 src/PHPExif/Adapter/Native/ReaderConfig.php delete mode 100644 src/PHPExif/Reader.php delete mode 100644 src/PHPExif/ReaderInterface.php delete mode 100644 tests/PHPExif/ReaderTest.php diff --git a/src/PHPExif/Adapter/Native/Reader/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php similarity index 99% rename from src/PHPExif/Adapter/Native/Reader/Mapper.php rename to src/PHPExif/Adapter/Native/Mapper.php index 9876022..2efe289 100644 --- a/src/PHPExif/Adapter/Native/Reader/Mapper.php +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -11,7 +11,7 @@ * @package Exif */ -namespace PHPExif\Adapter\Native\Mapper; +namespace PHPExif\Adapter\Native; use PHPExif\Adapter\MapperInterface; use PHPExif\Data\Exif; diff --git a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php new file mode 100644 index 0000000..2b9ebba --- /dev/null +++ b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php @@ -0,0 +1,100 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + */ + +namespace PHPExif\Adapter\Native; + +use PHPExif\Adapter\AdapterConfig; +use PHPExif\Adapter\Native\Reader; +use PHPExif\Adapter\Native\ReaderConfig; + +/** + * NativeAdapterConfig + * + * @category PHPExif + * @package Adapter + */ +final class NativeAdapterConfig implements AdapterConfig +{ + const ENABLE = true; + const DISABLE = false; + /** + * @var array + */ + private $config; + + /** + * Config constructor + * + * @param array $config Optional changes to the default configuration + */ + public function __construct(array $config = array()) + { + $config = array_replace_recursive( + $this->getDefaultConfig(), + $config + ); + + // @todo Add validation + $this->config = $config; + } + + /** + * Returns the default config for the Native adapter + * + * @return array + */ + private function getDefaultConfig() + { + return array( + AdapterConfig::READER => array( + ReaderConfig::CONFIG_PARSE_RAW_IPTC_DATA => self::ENABLE, + ReaderConfig::CONFIG_SECTIONS => 'ANY_TAG', + + ), + ); + } + + /** + * {@inheritDoc} + */ + public function factory($type) + { + switch ($type) { + case AdapterConfig::READER: + return $this->getReader(); + case AdapterConfig::WRITER: + default: + throw new \InvalidArgumentException( + sprintf( + 'No factory available for type "%1$s"', + $type + ) + ); + break; + } + } + + /** + * Returns new correctly instantiated Reader + * + * @return Reader + */ + private function getReader() + { + $reader = new Reader( + ReaderConfig::fromArray( + $this->config[AdapterConfig::READER] + ) + ); + + return $reader; + } +} diff --git a/src/PHPExif/Adapter/Native/Reader/Reader.php b/src/PHPExif/Adapter/Native/Reader.php similarity index 58% rename from src/PHPExif/Adapter/Native/Reader/Reader.php rename to src/PHPExif/Adapter/Native/Reader.php index 1af147e..0f7df6f 100644 --- a/src/PHPExif/Adapter/Native/Reader/Reader.php +++ b/src/PHPExif/Adapter/Native/Reader.php @@ -7,10 +7,10 @@ * @copyright Copyright (c) 2013 Tom Van Herreweghe * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Exif + * @package Adapter */ -namespace PHPExif\Adapter\Native\Reader; +namespace PHPExif\Adapter\Native; use PHPExif\Adapter\MapperInterface; use PHPExif\Adapter\ReaderInterface; @@ -21,12 +21,12 @@ * Reader class * * @category PHPExif - * @package Exif + * @package Adapter */ final class Reader implements ReaderInterface { /** - * @var Configuration + * @var ReaderConfig */ private $configuration; @@ -36,34 +36,15 @@ final class Reader implements ReaderInterface private $mapper; /** - * @param Configuration $configuration + * @param ReaderConfig $configuration */ - public function __construct(Configuration $configuration) + public function __construct(ReaderConfig $configuration) { $this->configuration = $configuration; } /** - * Returns an instance with sane defaults - * everyone can agree on - * - * @return Reader - */ - public static function withDefaults() - { - $instance = new Reader( - new Configuration - ); - - return $instance; - } - - /** - * Returns an instance of the configured mapper class - * - * @throws UnknownAdapterTypeException - * - * @return MapperInterface + * {@inheritDoc} */ public function getMapper() { @@ -71,29 +52,19 @@ public function getMapper() return $this->mapper; } - $this-> mapper = $this->initializeMapper(); + $this->setMapper( + new Mapper + ); return $this->mapper; } /** - * Creates a new MapperInterface instance - * from given Configuration - * - * @return MapperInterface + * {@inheritDoc} */ - private function initializeMapper() + public function setMapper(MapperInterface $mapper) { - $mapper = new $this->configuration->mapperClass; - - if (!$mapper instanceof MapperInterface) { - throw UnknownAdapterTypeException::noInterface( - $this->configuration->mapperClass, - 'PHPExif\\Adapter\\MapperInterface' - ); - } - - return $mapper; + $this->mapper = $mapper; } /** @@ -105,16 +76,16 @@ public function getMetadataFromFile($filePath) { $data = @exif_read_data( $filePath, - Configuration::SECTIONS, - Configuration::SECTIONS_FLAT, - Configuration::NO_THUMBNAIL + $this->configuration->getSections(), + false, // flat array + false // no thumbnail ); if (false === $data) { throw NoExifDataException::fromFile($filePath); } - $this->augmentDataWithIptcRawData($data); + $this->augmentDataWithIptcRawData($filePath, $data); // map the data: $mapper = $this->getMapper(); @@ -126,20 +97,23 @@ public function getMetadataFromFile($filePath) /** * Adds data from iptcparse to the original raw EXIF data * + * @param string $filePath * @param array $data * * @return void */ - private function augmentDataWithIptcRawData(array &$data) + private function augmentDataWithIptcRawData($filePath, array &$data) { - if (!$this->configuration->parseRawIptcData) { + if (!$this->configuration->isParseRawIptcData()) { return; } - getimagesize($file, $info); + getimagesize($filePath, $info); + if (!array_key_exists('APP13', $info)) { return; } + $iptcRawData = iptcparse($info['APP13']); // UTF8 diff --git a/src/PHPExif/Adapter/Native/Reader/Configuration.php b/src/PHPExif/Adapter/Native/Reader/Configuration.php deleted file mode 100644 index b18325f..0000000 --- a/src/PHPExif/Adapter/Native/Reader/Configuration.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Exif - */ - -namespace PHPExif\Adapter\Native\Reader; - -/** - * Configuration class - * - * @category PHPExif - * @package Exif - */ -final class Configuration -{ - const INCLUDE_THUMBNAIL = true; - const NO_THUMBNAIL = false; - - const SECTIONS_AS_ARRAYS = true; - const SECTIONS_FLAT = false; - - const SECTIONS = 'ANY_TAG'; - - const IPTC_EXIF_ONLY = false; - const IPTC_ADD_RAW = true; - - /** - * Classname of the Mapper to use when mapping raw data - * to an Exif object - * - * @var string - */ - public $mapperClass = '\\PHPExif\\Adapter\\Native\\Mapper'; - - /** - * Parse IPTC data from binary data and add it to the - * data read from Exif? - * - * @var bool - */ - public $parseRawIptcData = self::IPTC_ADD_RAW; -} diff --git a/src/PHPExif/Adapter/Native/ReaderConfig.php b/src/PHPExif/Adapter/Native/ReaderConfig.php new file mode 100644 index 0000000..1ec9d78 --- /dev/null +++ b/src/PHPExif/Adapter/Native/ReaderConfig.php @@ -0,0 +1,84 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + */ + +namespace PHPExif\Adapter\Native\Reader; + +/** + * ReaderConfig class + * + * @category PHPExif + * @package Adapter + */ +final class ReaderConfig +{ + const CONFIG_PARSE_RAW_IPTC_DATA = 'parseRawIptcData'; + const CONFIG_SECTIONS = 'sections'; + + /** + * Parse raw IPTC data and augment the metadata with it + * + * @var bool + */ + private $parseRawIptcData; + + /** + * List of sections to retrieve + * + * @var string + */ + private $sections; + + /** + * @param bool $parseRawIptcData + * @param string $sections + */ + public function __construct($parseRawIptcData, $sections) + { + $this->parseRawIptcData = (bool) $parseRawIptcData; + $this->sections = $sections; + } + + /** + * Returns if the raw IPTC data should be retrieved + * + * @return bool + */ + public function isParseRawIptcData() + { + return $this->parseRawIptcData; + } + + /** + * Returns the list of wanted sections + * + * @return string + */ + public function getSections() + { + return $this->sections; + } + + /** + * Creates new instance from given array of config values + * + * @param array $config + * + * @return ReaderConfig + */ + public static function fromArray(array $config) + { + return new self( + $config[self::CONFIG_PARSE_RAW_IPTC_DATA], + $config[self::CONFIG_SECTIONS] + ); + } +} diff --git a/src/PHPExif/Adapter/ReaderInterface.php b/src/PHPExif/Adapter/ReaderInterface.php index 2d5fa67..4370417 100644 --- a/src/PHPExif/Adapter/ReaderInterface.php +++ b/src/PHPExif/Adapter/ReaderInterface.php @@ -23,6 +23,22 @@ */ interface ReaderInterface { + /** + * Accessor for the data mapper + * + * @return MapperInterface + */ + public function getMapper(); + + /** + * Mutator for the data mapper + * + * @param MapperInterface $mapper + * + * @return void + */ + public function setMapper(MapperInterface $mapper); + /** * Read the available metadata of given file * diff --git a/src/PHPExif/Reader.php b/src/PHPExif/Reader.php deleted file mode 100644 index 642a9ff..0000000 --- a/src/PHPExif/Reader.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Exif - */ - -namespace PHPExif; - -use PHPExif\Adapter\Native\Reader\Reader as NativeReader; -use PHPExif\Adapter\ReaderInterface as AdapterReaderInterface; -use PHPExif\Exception\UnknownAdapterTypeException; - -/** - * Reader class - * - * Responsible for reading EXIF data from a file - * - * @category PHPExif - * @package Exif - */ -final class Reader implements ReaderInterface -{ - /** - * The current adapter - * - * @var \PHPExif\Adapter\ReaderInterface - */ - private $adapter; - - /** - * Reader constructor - * - * @param \PHPExif\Adapter\ReaderInterface $adapter - */ - public function __construct(AdapterReaderInterface $adapter) - { - $this->adapter = $adapter; - } - - /** - * {@inheritDoc} - */ - public function getAdapter() - { - return $this->adapter; - } - - /** - * {@inheritDoc} - */ - public static function factory($type) - { - switch ($type) { - case self::TYPE_NATIVE: - $adapter = NativeReader::withDefaults(); - break; - /* - case self::TYPE_EXIFTOOL: - $adapter = new ExiftoolAdapter(); - break; - */ - default: - throw UnknownAdapterTypeException::forType($type); - } - - $classname = get_called_class(); - - return new $classname($adapter); - } - - /** - * {@inheritDoc} - */ - public function getMetadataFromFile($file) - { - return $this->getAdapter()->getMetadataFromFile($file); - } -} diff --git a/src/PHPExif/ReaderInterface.php b/src/PHPExif/ReaderInterface.php deleted file mode 100644 index 13a7b95..0000000 --- a/src/PHPExif/ReaderInterface.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License - * @category PHPExif - * @package Exif - */ - -namespace PHPExif; - -use PHPExif\Data\MetadataInterface; -use PHPExif\Exception\UnknownAdapterTypeException; - -/** - * ReaderInterface - * - * Public API for reading EXIF data - * - * @category PHPExif - * @package Exif - */ -interface ReaderInterface -{ - const TYPE_NATIVE = 'native'; - const TYPE_EXIFTOOL = 'exiftool'; - - /** - * Getter for the reader adapter - * - * @return \PHPExif\Adapter\ReaderInterface - */ - public function getAdapter(); - - /** - * Factory for the reader - * - * @param string $type - * - * @throws UnknownAdapterTypeException When given type is invalid - * - * @return ReaderInterface - */ - public static function factory($type); - - /** - * Reads & parses the EXIF data from given file - * - * @param string $file - * - * @return MetadataInterface - */ - public function getMetadataFromFile($file); -} diff --git a/tests/PHPExif/ReaderTest.php b/tests/PHPExif/ReaderTest.php deleted file mode 100644 index e406997..0000000 --- a/tests/PHPExif/ReaderTest.php +++ /dev/null @@ -1,87 +0,0 @@ - - */ -class ReaderTest extends \PHPUnit_Framework_TestCase -{ - /** - * @group reader - * @covers \PHPExif\Reader::getAdapter - */ - public function testGetAdapterReturnsFromProperty() - { - $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') - ->getMock(); - $reader = new \PHPExif\Reader($adapter); - - $reflProperty = new \ReflectionProperty('\\PHPExif\\Reader', 'adapter'); - $reflProperty->setAccessible(true); - - $reflProperty->setValue($reader, $adapter); - - $this->assertSame( - $adapter, - $reader->getAdapter() - ); - } - - /** - * @group reader - * @covers \PHPExif\Reader::factory - * @expectedException \PHPExif\Exception\UnknownAdapterTypeException - */ - public function testFactoryThrowsExceptionForUnknownType() - { - $type = 'foo'; - $instance = Reader::factory($type); - } - - /** - * @group reader - * @covers \PHPExif\Reader::factory - */ - public function testFactoryForNativeReturnsInstance() - { - $type = Reader::TYPE_NATIVE; - $instance = Reader::factory($type); - - $this->assertInstanceOf('\\PHPExif\\Reader', $instance); - } - - /** - * @group reader - * @covers \PHPExif\Reader::factory - */ - public function testFactoryForNativeReturnsInstanceWithCorrectAdapter() - { - $type = Reader::TYPE_NATIVE; - $instance = Reader::factory($type); - $adapter = $instance->getAdapter(); - - $this->assertInstanceOf( - '\\PHPExif\\Adapter\\Native\\Reader\\Reader', - $adapter - ); - } - - /** - * @group reader - * @covers \PHPExif\Reader::getMetadataFromFile - */ - public function testReadForwardsToAdapter() - { - $file = '/path/to/a/file'; - $adapter = $this->getMockBuilder('\\PHPExif\\Adapter\\ReaderInterface') - ->getMock(); - $adapter->expects($this->once()) - ->method('getMetadataFromFile') - ->with( - $this->equalTo($file) - ); - - $reader = new \PHPExif\Reader($adapter); - $reader->getMetadataFromFile($file); - } -} From 1a6946a087d338c4c7e0b23f5fa88e203f8b7ee6 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 25 Feb 2016 22:43:14 +0100 Subject: [PATCH 18/51] Updated the README & created CONTRIBUTING information Signed-off-by: Tom Van Herreweghe --- CONTRIBUTING.md | 29 +++++++++++++++++++++++++++++ README.md | 24 +++++------------------- 2 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b8d594b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# Contributing + +## Branching strategy + +PHPExif uses the [Git Flow](https://github.com/nvie/gitflow) branching strategy. + +TL;DR: + +- Work on a new version is merged in the `develop` branch +- Current stable release is in the `master` branch +- Hotfixes: branch from `master` +- New feature: branch from `develop` +- Bugfix for older MAJOR version: branch from MAJOR release branch + +## Coding Standards + +PHPExif is written according the [PSR-0/1/2 standards](http://www.php-fig.org/). When submitting code, please make sure it is conform these standards. + +## Testing + +PHPExif is unit tested with [PHPUnit](https://phpunit.de/). We aim to have all functionality covered by unit tests. When submitting patches, you are strongly encouraged to provide unit tests. Patches without tests are not accepted. + +## Code Coverage + +Code coverage is checked by [Coveralls](https://coveralls.io/repos/Miljar/php-exif). Respect the boy scout rule for PHP developers: Always try to keep the Code Coverage level on par or above with the current level. + +## Most important Rule + +All contributions are welcomed and greatly appreciated. diff --git a/README.md b/README.md index 3589e40..47b1054 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# [PHPExif v0.5.1](http://github.com/Miljar/php-exif) [![Build Status](https://travis-ci.org/Miljar/php-exif.png?branch=master)](https://travis-ci.org/Miljar/php-exif) [![Coverage Status](https://coveralls.io/repos/Miljar/php-exif/badge.svg?branch=master)](https://coveralls.io/r/Miljar/php-exif?branch=master) [![Code Climate](https://codeclimate.com/github/Miljar/php-exif/badges/gpa.svg)](https://codeclimate.com/github/Miljar/php-exif) +# [PHPExif v1.0.0-prealpha](http://github.com/Miljar/php-exif) [![Build Status](https://travis-ci.org/Miljar/php-exif.png?branch=feature/rewrite)](https://travis-ci.org/Miljar/php-exif) [![Coverage Status](https://coveralls.io/repos/Miljar/php-exif/badge.svg?branch=feature/rewrite)](https://coveralls.io/r/Miljar/php-exif?branch=feature/rewrite) [![Code Climate](https://codeclimate.com/github/Miljar/php-exif/badges/gpa.svg)](https://codeclimate.com/github/Miljar/php-exif) PHPExif is a library which gives you easy access to the EXIF meta-data of an image. @@ -7,29 +7,15 @@ PHPExif serves as a wrapper around some native or CLI tools which access this EX ## Supported tools * Native PHP functionality (exif_read_data, iptcparse) -* [Exiftool](http://www.sno.phy.queensu.ca/~phil/exiftool) adapter (wrapper for the exiftool binary) +* @todo: [Exiftool](http://www.sno.phy.queensu.ca/~phil/exiftool) adapter (wrapper for the exiftool binary) -## Installation (composer) +## Documentation -```json -"miljar/php-exif": "~0.5.0" -``` - - -## Usage - -[Before v0.3.0](Resources/doc/usage_0.2.1.md) - -[v0.3.0+](Resources/doc/usage.md) +@todo - Write docs & publish on readthedocs.org ## Contributing -Please submit all pull requests against the correct branch. The release branch for the next version is a branch with the same name as the next version. Bugfixes should go in the master branch, unless they are for code in a new release branch. - -PHPExif is written according the [PSR-0/1/2 standards](http://www.php-fig.org/). When submitting code, please make sure it is conform these standards. -We aim to have all functionality covered by unit tests. When submitting code, you are strongly encouraged to unit test your code and to keep the level of code coverage on par with the current level. - -All contributions are welcomed and greatly appreciated. +See [CONTRIBUTING.md](CONTRIBUTING.md) for more information. ## Feedback From a8ebeb49810a1ab18de8828817bc224e4ae01f11 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 25 Feb 2016 22:52:06 +0100 Subject: [PATCH 19/51] Reverted php-coverals to 0.6.x Signed-off-by: Tom Van Herreweghe --- composer.json | 2 +- composer.lock | 658 ++++++++------------------------------------------ 2 files changed, 101 insertions(+), 559 deletions(-) diff --git a/composer.json b/composer.json index 63b9548..138d923 100755 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "phpmd/phpmd": "~2.2.0", "squizlabs/php_codesniffer": "~2.0", "phpunit/phpunit": "~4.5.0", - "satooshi/php-coveralls": "~0.6" + "satooshi/php-coveralls": "~0.6.0" }, "suggest": { "lib-exiftool": "Use perl lib exiftool as adapter" diff --git a/composer.lock b/composer.lock index 29cd0b5..199f9e1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,76 +4,10 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "e2c68dea9211298714ff36e4e05a9457", - "content-hash": "a10f7df39b899fc8f73d61c82a9026e1", + "hash": "0ad33c09956b8534fcb5fcafc83f6189", + "content-hash": "7ca529a72ea09ed6e3ccf5b47efe7862", "packages": [], "packages-dev": [ - { - "name": "doctrine/collections", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "866e100a425b8b73d15393fd081c6bf067f05bf9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/866e100a425b8b73d15393fd081c6bf067f05bf9", - "reference": "866e100a425b8b73d15393fd081c6bf067f05bf9", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "array", - "collections", - "iterator" - ], - "time": "2015-09-11 15:24:21" - }, { "name": "doctrine/instantiator", "version": "dev-master", @@ -129,95 +63,70 @@ "time": "2015-06-14 21:17:01" }, { - "name": "gitonomy/gitlib", - "version": "v0.1.8", + "name": "guzzle/guzzle", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/gitonomy/gitlib.git", - "reference": "f575b8f7da917ade7890c6aa705fa22545690389" + "url": "https://github.com/guzzle/guzzle3.git", + "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/gitonomy/gitlib/zipball/f575b8f7da917ade7890c6aa705fa22545690389", - "reference": "f575b8f7da917ade7890c6aa705fa22545690389", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/b3f5050cb6270c7a728a0b74ac2de50a262b3e02", + "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02", "shasum": "" }, "require": { - "symfony/process": "^2.3|^3.0" + "ext-curl": "*", + "php": ">=5.3.3", + "symfony/event-dispatcher": "~2.1" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-error-response": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" }, "require-dev": { - "psr/log": "^1.0" + "doctrine/cache": "~1.3", + "monolog/monolog": "~1.0", + "phpunit/phpunit": "3.7.*", + "psr/log": "~1.0", + "symfony/class-loader": "~2.1", + "zendframework/zend-cache": "2.*,<2.3", + "zendframework/zend-log": "2.*,<2.3" }, "suggest": { - "psr/log": "Add some log" + "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "3.9-dev" } }, "autoload": { - "psr-4": { - "Gitonomy\\Git\\": "src/Gitonomy/Git/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alexandre Salomé", - "email": "alexandre.salome@gmail.com", - "homepage": "http://alexandre-salome.fr" - }, - { - "name": "Julien DIDIER", - "email": "genzo.wm@gmail.com", - "homepage": "http://www.jdidier.net" - } - ], - "description": "Library for accessing git", - "homepage": "http://gitonomy.com", - "time": "2015-12-01 22:25:57" - }, - { - "name": "guzzlehttp/guzzle", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "739b9c8378c462943c42fee5353453ab4164ed8e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/739b9c8378c462943c42fee5353453ab4164ed8e", - "reference": "739b9c8378c462943c42fee5353453ab4164ed8e", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.1", - "php": ">=5.5.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0", - "psr/log": "~1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.2-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" + "psr-0": { + "Guzzle": "src/", + "Guzzle\\Tests": "tests/" } }, "notification-url": "https://packagist.org/downloads/", @@ -229,9 +138,13 @@ "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" } ], - "description": "Guzzle is a PHP HTTP client library", + "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", "homepage": "http://guzzlephp.org/", "keywords": [ "client", @@ -242,116 +155,7 @@ "rest", "web service" ], - "time": "2016-02-17 21:09:10" - }, - { - "name": "guzzlehttp/promises", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "dc03e97371e37172ff94547980f898659de76ffc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/dc03e97371e37172ff94547980f898659de76ffc", - "reference": "dc03e97371e37172ff94547980f898659de76ffc", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-02-23 21:19:12" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "PSR-7 message implementation", - "keywords": [ - "http", - "message", - "stream", - "uri" - ], - "time": "2016-02-18 21:54:00" + "time": "2015-04-29 17:06:53" }, { "name": "pdepend/pdepend", @@ -932,81 +736,24 @@ ], "time": "2015-10-02 06:51:40" }, - { - "name": "psr/http-message", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "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", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2015-05-04 20:22:00" - }, { "name": "psr/log", - "version": "dev-master", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e" + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d8e60a5619fff77f9669da8997697443ef1a1d7e", - "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", "shasum": "" }, - "require": { - "php": ">=5.3.0" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "psr-0": { + "Psr\\Log\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1020,65 +767,58 @@ } ], "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", "keywords": [ "log", "psr", "psr-3" ], - "time": "2016-01-06 21:40:42" + "time": "2012-12-21 11:40:51" }, { "name": "satooshi/php-coveralls", - "version": "dev-master", + "version": "v0.6.1", "source": { "type": "git", "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "8384919da59b11763db611dccc5ca141f32533c5" + "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/8384919da59b11763db611dccc5ca141f32533c5", - "reference": "8384919da59b11763db611dccc5ca141f32533c5", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", + "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", "shasum": "" }, "require": { + "ext-curl": "*", "ext-json": "*", "ext-simplexml": "*", - "guzzlehttp/guzzle": "^6.0", - "php": ">=5.5", - "psr/log": "^1.0", - "symfony/config": "^2.1|^3.0", - "symfony/console": "^2.1|^3.0", - "symfony/stopwatch": "^2.0|^3.0", - "symfony/yaml": "^2.0|^3.0" + "guzzle/guzzle": ">=3.0", + "php": ">=5.3", + "psr/log": "1.0.0", + "symfony/config": ">=2.0", + "symfony/console": ">=2.0", + "symfony/stopwatch": ">=2.2", + "symfony/yaml": ">=2.0" }, "require-dev": { - "apigen/apigen": "^2.8", - "pdepend/pdepend": "^2.2", - "phpmd/phpmd": "^2.0", - "phpunit/php-invoker": "^1.1", - "phpunit/phpunit": "^4.0", - "sebastian/finder-facade": "^1.1", - "sebastian/phpcpd": "^1.4", - "squizlabs/php_codesniffer": "^1.4", - "theseer/fdomdocument": "^1.6" - }, - "suggest": { - "symfony/http-kernel": "Allows Symfony integration" + "apigen/apigen": "2.8.*@stable", + "pdepend/pdepend": "dev-master", + "phpmd/phpmd": "dev-master", + "phpunit/php-invoker": ">=1.1.0,<1.2.0", + "phpunit/phpunit": "3.7.*@stable", + "sebastian/finder-facade": "dev-master", + "sebastian/phpcpd": "1.4.*@stable", + "squizlabs/php_codesniffer": "1.4.*@stable", + "theseer/fdomdocument": "dev-master" }, "bin": [ "composer/bin/coveralls" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.7-dev" - } - }, "autoload": { - "psr-4": { - "Satooshi\\": "src/Satooshi/" + "psr-0": { + "Contrib\\Component": "src/", + "Contrib\\Bundle": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1100,7 +840,7 @@ "github", "test" ], - "time": "2015-12-05 02:06:10" + "time": "2013-05-04 08:07:33" }, { "name": "sebastian/comparator", @@ -1474,64 +1214,18 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2015-06-21 13:59:46" }, - { - "name": "seld/jsonlint", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "66834d3e3566bb5798db7294619388786ae99394" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/66834d3e3566bb5798db7294619388786ae99394", - "reference": "66834d3e3566bb5798db7294619388786ae99394", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "time": "2015-11-21 02:21:41" - }, { "name": "squizlabs/php_codesniffer", "version": "dev-master", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "825c050244393fc4231e5bf97f7569c2831795aa" + "reference": "be0a7044ec8f664c07f117e86633250122af6dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/825c050244393fc4231e5bf97f7569c2831795aa", - "reference": "825c050244393fc4231e5bf97f7569c2831795aa", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/be0a7044ec8f664c07f117e86633250122af6dbf", + "reference": "be0a7044ec8f664c07f117e86633250122af6dbf", "shasum": "" }, "require": { @@ -1595,7 +1289,7 @@ "phpcs", "standards" ], - "time": "2016-02-22 03:53:15" + "time": "2016-02-25 21:37:34" }, { "name": "symfony/config", @@ -1771,27 +1465,27 @@ }, { "name": "symfony/event-dispatcher", - "version": "dev-master", + "version": "2.8.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9d7930726e060b0c45ae10022a4cb307e502500b" + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9d7930726e060b0c45ae10022a4cb307e502500b", - "reference": "9d7930726e060b0c45ae10022a4cb307e502500b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/78c468665c9568c3faaa9c416a7134308f2d85c3", + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0", - "symfony/dependency-injection": "~2.8|~3.0", - "symfony/expression-language": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0" + "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" }, "suggest": { "symfony/dependency-injection": "", @@ -1800,7 +1494,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -1827,7 +1521,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-02-04 12:57:09" + "time": "2016-01-27 05:14:19" }, { "name": "symfony/filesystem", @@ -1878,109 +1572,6 @@ "homepage": "https://symfony.com", "time": "2016-02-23 16:17:05" }, - { - "name": "symfony/finder", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "43a0bde21f9f390131917b6202eb02b3fea1f799" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/43a0bde21f9f390131917b6202eb02b3fea1f799", - "reference": "43a0bde21f9f390131917b6202eb02b3fea1f799", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2016-02-04 12:57:09" - }, - { - "name": "symfony/options-resolver", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "0d15b40701e1778bdbc206c8545ad423402021c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0d15b40701e1778bdbc206c8545ad423402021c4", - "reference": "0d15b40701e1778bdbc206c8545ad423402021c4", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony OptionsResolver Component", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "time": "2016-01-21 10:01:50" - }, { "name": "symfony/polyfill-mbstring", "version": "dev-master", @@ -2040,55 +1631,6 @@ ], "time": "2016-01-20 09:13:37" }, - { - "name": "symfony/process", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "650a91315648fe433824e454b2c7107926f9876b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/650a91315648fe433824e454b2c7107926f9876b", - "reference": "650a91315648fe433824e454b2c7107926f9876b", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Process Component", - "homepage": "https://symfony.com", - "time": "2016-02-04 12:57:09" - }, { "name": "symfony/stopwatch", "version": "dev-master", From ed0d731b4975ec63c8e35517a7d5a618cd4f5f85 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sat, 27 Feb 2016 13:08:02 +0100 Subject: [PATCH 20/51] Updated dev dependencies Signed-off-by: Tom Van Herreweghe --- composer.json | 8 +- composer.lock | 370 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 261 insertions(+), 117 deletions(-) diff --git a/composer.json b/composer.json index 138d923..749e83c 100755 --- a/composer.json +++ b/composer.json @@ -12,13 +12,13 @@ ], "keywords": ["EXIF", "IPTC", "jpeg", "tiff", "exiftool"], "require": { - "php": "~5.3" + "php": "~5.6.0" }, "require-dev": { - "phpmd/phpmd": "~2.2.0", + "phpmd/phpmd": "~2.3.0", "squizlabs/php_codesniffer": "~2.0", - "phpunit/phpunit": "~4.5.0", - "satooshi/php-coveralls": "~0.6.0" + "phpunit/phpunit": "~5.2.0", + "satooshi/php-coveralls": "~1.0.0" }, "suggest": { "lib-exiftool": "Use perl lib exiftool as adapter" diff --git a/composer.lock b/composer.lock index 199f9e1..f023ffd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "0ad33c09956b8534fcb5fcafc83f6189", - "content-hash": "7ca529a72ea09ed6e3ccf5b47efe7862", + "hash": "acd2ce0338c49658f168941d5a1a68b5", + "content-hash": "6d2ad1edf1104b827e3d00d343188e8c", "packages": [], "packages-dev": [ { @@ -157,6 +157,48 @@ ], "time": "2015-04-29 17:06:53" }, + { + "name": "myclabs/deep-copy", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "e3abefcd7f106677fd352cd7c187d6c969aa9ddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e3abefcd7f106677fd352cd7c187d6c969aa9ddc", + "reference": "e3abefcd7f106677fd352cd7c187d6c969aa9ddc", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2015-11-07 22:20:37" + }, { "name": "pdepend/pdepend", "version": "2.2.3", @@ -248,28 +290,25 @@ }, { "name": "phpmd/phpmd", - "version": "2.2.3", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpmd/phpmd.git", - "reference": "5eeb5a4d39c8304910b33ae49f8813905346cc35" + "reference": "08b5bcd454a7148579b68931fc500d824afd3bb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/5eeb5a4d39c8304910b33ae49f8813905346cc35", - "reference": "5eeb5a4d39c8304910b33ae49f8813905346cc35", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/08b5bcd454a7148579b68931fc500d824afd3bb5", + "reference": "08b5bcd454a7148579b68931fc500d824afd3bb5", "shasum": "" }, "require": { "pdepend/pdepend": "~2.0", - "php": ">=5.3.0", - "symfony/config": ">=2.4", - "symfony/dependency-injection": ">=2.4", - "symfony/filesystem": ">=2.4" + "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "*", - "squizlabs/php_codesniffer": "*" + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.0" }, "bin": [ "src/bin/phpmd" @@ -289,12 +328,18 @@ "name": "Manuel Pichler", "email": "github@manuel-pichler.de", "homepage": "https://github.com/manuelpichler", - "role": "Project Founder" + "role": "Project founder" }, { "name": "Other contributors", "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", "role": "Contributors" + }, + { + "name": "Marc Würth", + "email": "ravage@bluewin.ch", + "homepage": "https://github.com/ravage84", + "role": "Project Maintainer" } ], "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", @@ -306,7 +351,7 @@ "phpmd", "pmd" ], - "time": "2015-05-27 18:16:57" + "time": "2015-09-24 14:37:49" }, { "name": "phpspec/prophecy", @@ -372,29 +417,30 @@ }, { "name": "phpunit/php-code-coverage", - "version": "2.2.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "reference": "a58f95ae76fe201b571fad3e8370a50c4368678c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a58f95ae76fe201b571fad3e8370a50c4368678c", + "reference": "a58f95ae76fe201b571fad3e8370a50c4368678c", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": "^5.6 || ^7.0", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" + "sebastian/version": "~1.0|~2.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" + "phpunit/phpunit": "~5" }, "suggest": { "ext-dom": "*", @@ -404,7 +450,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { @@ -430,35 +476,37 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2016-02-18 07:31:12" }, { "name": "phpunit/php-file-iterator", - "version": "1.3.4", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, "autoload": { "classmap": [ - "File/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -475,7 +523,7 @@ "filesystem", "iterator" ], - "time": "2013-10-10 15:34:57" + "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", @@ -520,7 +568,7 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", @@ -610,16 +658,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.5.x-dev", + "version": "5.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4" + "reference": "dbd80d79c7271ff42af453c8a1b387691b555f9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d6429b0995b24a2d9dfe5587ee3a7071c1161af4", - "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/dbd80d79c7271ff42af453c8a1b387691b555f9a", + "reference": "dbd80d79c7271ff42af453c8a1b387691b555f9a", "shasum": "" }, "require": { @@ -628,20 +676,22 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "~1.3,>=1.3.1", - "phpunit/php-code-coverage": "~2.0,>=2.0.11", - "phpunit/php-file-iterator": "~1.3.2", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "^3.2.1", + "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0.2", - "phpunit/phpunit-mock-objects": "~2.3", + "phpunit/php-timer": ">=1.0.6", + "phpunit/phpunit-mock-objects": ">=3.0.5", "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.1", - "sebastian/environment": "~1.2", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.0" + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", + "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" @@ -652,7 +702,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.5.x-dev" + "dev-master": "5.2.x-dev" } }, "autoload": { @@ -678,30 +728,30 @@ "testing", "xunit" ], - "time": "2015-03-29 09:24:05" + "time": "2016-02-23 11:55:17" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "reference": "c4dd0c9e7fcbf53c6aa48012902be692318c7566" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c4dd0c9e7fcbf53c6aa48012902be692318c7566", + "reference": "c4dd0c9e7fcbf53c6aa48012902be692318c7566", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", + "php": ">=5.6", "phpunit/php-text-template": "~1.2", "sebastian/exporter": "~1.2" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "~5" }, "suggest": { "ext-soap": "*" @@ -709,7 +759,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -734,26 +784,34 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2015-12-08 08:54:19" }, { "name": "psr/log", - "version": "1.0.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "url": "https://api.github.com/repos/php-fig/log/zipball/d8e60a5619fff77f9669da8997697443ef1a1d7e", + "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e", "shasum": "" }, + "require": { + "php": ">=5.3.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "psr-0": { - "Psr\\Log\\": "" + "psr-4": { + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -767,58 +825,49 @@ } ], "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ "log", "psr", "psr-3" ], - "time": "2012-12-21 11:40:51" + "time": "2016-01-06 21:40:42" }, { "name": "satooshi/php-coveralls", - "version": "v0.6.1", + "version": "1.0.x-dev", "source": { "type": "git", "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760" + "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", - "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/da51d304fe8622bf9a6da39a8446e7afd432115c", + "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c", "shasum": "" }, "require": { - "ext-curl": "*", "ext-json": "*", "ext-simplexml": "*", - "guzzle/guzzle": ">=3.0", - "php": ">=5.3", - "psr/log": "1.0.0", - "symfony/config": ">=2.0", - "symfony/console": ">=2.0", - "symfony/stopwatch": ">=2.2", - "symfony/yaml": ">=2.0" + "guzzle/guzzle": "^2.8|^3.0", + "php": ">=5.3.3", + "psr/log": "^1.0", + "symfony/config": "^2.1|^3.0", + "symfony/console": "^2.1|^3.0", + "symfony/stopwatch": "^2.0|^3.0", + "symfony/yaml": "^2.0|^3.0" }, - "require-dev": { - "apigen/apigen": "2.8.*@stable", - "pdepend/pdepend": "dev-master", - "phpmd/phpmd": "dev-master", - "phpunit/php-invoker": ">=1.1.0,<1.2.0", - "phpunit/phpunit": "3.7.*@stable", - "sebastian/finder-facade": "dev-master", - "sebastian/phpcpd": "1.4.*@stable", - "squizlabs/php_codesniffer": "1.4.*@stable", - "theseer/fdomdocument": "dev-master" + "suggest": { + "symfony/http-kernel": "Allows Symfony integration" }, "bin": [ - "composer/bin/coveralls" + "bin/coveralls" ], "type": "library", "autoload": { - "psr-0": { - "Contrib\\Component": "src/", - "Contrib\\Bundle": "src/" + "psr-4": { + "Satooshi\\": "src/Satooshi/" } }, "notification-url": "https://packagist.org/downloads/", @@ -840,7 +889,52 @@ "github", "test" ], - "time": "2013-05-04 08:07:33" + "time": "2016-01-20 17:35:46" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2016-02-13 06:45:14" }, { "name": "sebastian/comparator", @@ -964,12 +1058,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6e7133793a8e5a5714a551a8324337374be209df" + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", - "reference": "6e7133793a8e5a5714a551a8324337374be209df", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", "shasum": "" }, "require": { @@ -1006,7 +1100,7 @@ "environment", "hhvm" ], - "time": "2015-12-02 08:37:27" + "time": "2016-02-26 18:40:46" }, { "name": "sebastian/exporter", @@ -1179,21 +1273,71 @@ "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "time": "2016-01-28 05:39:29" }, + { + "name": "sebastian/resource-operations", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, { "name": "sebastian/version", - "version": "1.0.6", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", "shasum": "" }, + "require": { + "php": ">=5.6" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1212,7 +1356,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2016-02-04 12:56:52" }, { "name": "squizlabs/php_codesniffer", @@ -1410,12 +1554,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "7cdf5f9ca7d90b768189c759f338b0cf4ca05e76" + "reference": "338b4d287bb5c8cff07d0c9df7c015c2ffee939a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/7cdf5f9ca7d90b768189c759f338b0cf4ca05e76", - "reference": "7cdf5f9ca7d90b768189c759f338b0cf4ca05e76", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/338b4d287bb5c8cff07d0c9df7c015c2ffee939a", + "reference": "338b4d287bb5c8cff07d0c9df7c015c2ffee939a", "shasum": "" }, "require": { @@ -1461,7 +1605,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-02-22 01:22:58" + "time": "2016-02-26 05:59:04" }, { "name": "symfony/event-dispatcher", @@ -1682,25 +1826,25 @@ }, { "name": "symfony/yaml", - "version": "2.8.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995" + "reference": "13797a2598154e4663f31360733434e56924e20a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", - "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", + "url": "https://api.github.com/repos/symfony/yaml/zipball/13797a2598154e4663f31360733434e56924e20a", + "reference": "13797a2598154e4663f31360733434e56924e20a", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1727,7 +1871,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-02-23 07:41:20" + "time": "2016-02-18 10:31:35" } ], "aliases": [], @@ -1736,7 +1880,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~5.3" + "php": "~5.6.0" }, "platform-dev": [] } From 412312853c1faaf4abdf25dce7ca9d2dceafbfc6 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sat, 27 Feb 2016 13:08:21 +0100 Subject: [PATCH 21/51] Added minimum required versions of PHP to README Signed-off-by: Tom Van Herreweghe --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 47b1054..f8b2396 100755 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ PHPExif is a library which gives you easy access to the EXIF meta-data of an ima PHPExif serves as a wrapper around some native or CLI tools which access this EXIF meta-data from an image. As such, it provides a standard API for retrieving and accessing that information. +## Minimum requirements + +* 0.x branch: PHP 5.3 +* 1.x branch: PHP 5.6 + +See [http://php.net/supported-versions.php](http://php.net/supported-versions.php) for reason. + ## Supported tools * Native PHP functionality (exif_read_data, iptcparse) From 1914feb3cd3f89806bedff5aebed688f57028ed0 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 28 Feb 2016 20:56:24 +0100 Subject: [PATCH 22/51] Tests for Exceptions Signed-off-by: Tom Van Herreweghe --- composer.json | 3 ++ composer.lock | 26 ++++++------ .../AdapterAlreadyRegisteredExeptionTest.php | 25 +++++++++++ .../AdapterNotRegisteredExeptionTest.php | 25 +++++++++++ tests/PHPExif/Exception/BaseExceptionTest.php | 41 +++++++++++++++++++ .../ElementAlreadyExistsExeptionTest.php | 25 +++++++++++ .../ElementNotExistsExeptionTest.php | 25 +++++++++++ .../InvalidElementTypeExeptionTest.php | 25 +++++++++++ .../Exception/NoExifDataExceptionTest.php | 15 ++++--- .../UnknownAdapterTypeExceptionTest.php | 27 ++++++------ 10 files changed, 204 insertions(+), 33 deletions(-) create mode 100644 tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php create mode 100644 tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php create mode 100644 tests/PHPExif/Exception/BaseExceptionTest.php create mode 100644 tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php create mode 100644 tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php create mode 100644 tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php diff --git a/composer.json b/composer.json index 749e83c..84f91eb 100755 --- a/composer.json +++ b/composer.json @@ -26,5 +26,8 @@ "minimum-stability": "dev", "autoload": { "psr-4": { "PHPExif\\": "src/PHPExif/" } + }, + "autoload-dev": { + "psr-4": { "Tests\\PHPExif\\": "tests/PHPExif/" } } } diff --git a/composer.lock b/composer.lock index f023ffd..f2d4361 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "acd2ce0338c49658f168941d5a1a68b5", + "hash": "f32e7a7ee745431574de2977b839b9d3", "content-hash": "6d2ad1edf1104b827e3d00d343188e8c", "packages": [], "packages-dev": [ @@ -1494,12 +1494,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "50c745b4f1047632f7e46a70ba010789c4a9e385" + "reference": "200f109d77649eac204aee729cfc8760f02b3ade" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/50c745b4f1047632f7e46a70ba010789c4a9e385", - "reference": "50c745b4f1047632f7e46a70ba010789c4a9e385", + "url": "https://api.github.com/repos/symfony/console/zipball/200f109d77649eac204aee729cfc8760f02b3ade", + "reference": "200f109d77649eac204aee729cfc8760f02b3ade", "shasum": "" }, "require": { @@ -1546,7 +1546,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-02-23 16:17:05" + "time": "2016-02-28 16:28:07" }, { "name": "symfony/dependency-injection", @@ -1554,12 +1554,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "338b4d287bb5c8cff07d0c9df7c015c2ffee939a" + "reference": "c6c4ab94df002d6f3648b488ca96727c4b9b2df8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/338b4d287bb5c8cff07d0c9df7c015c2ffee939a", - "reference": "338b4d287bb5c8cff07d0c9df7c015c2ffee939a", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c6c4ab94df002d6f3648b488ca96727c4b9b2df8", + "reference": "c6c4ab94df002d6f3648b488ca96727c4b9b2df8", "shasum": "" }, "require": { @@ -1605,7 +1605,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-02-26 05:59:04" + "time": "2016-02-28 16:50:15" }, { "name": "symfony/event-dispatcher", @@ -1830,12 +1830,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "13797a2598154e4663f31360733434e56924e20a" + "reference": "939b8e10c4e0e1135144fb09e12a3d32ff129e4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/13797a2598154e4663f31360733434e56924e20a", - "reference": "13797a2598154e4663f31360733434e56924e20a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/939b8e10c4e0e1135144fb09e12a3d32ff129e4a", + "reference": "939b8e10c4e0e1135144fb09e12a3d32ff129e4a", "shasum": "" }, "require": { @@ -1871,7 +1871,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-02-18 10:31:35" + "time": "2016-02-28 10:09:55" } ], "aliases": [], diff --git a/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php b/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php new file mode 100644 index 0000000..7919665 --- /dev/null +++ b/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php @@ -0,0 +1,25 @@ + + */ +class AdapterAlreadyRegisteredExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers \PHPExif\Exception\Adapter\AdapterAlreadyRegisteredException::withName + */ + public function testWithKeyReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + AdapterAlreadyRegisteredException::class, + 'withName', + array('foo') + ); + } +} diff --git a/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php b/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php new file mode 100644 index 0000000..8715152 --- /dev/null +++ b/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php @@ -0,0 +1,25 @@ + + */ +class AdapterNotRegisteredExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers \PHPExif\Exception\Adapter\AdapterNotRegisteredException::withName + */ + public function testWithKeyReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + AdapterNotRegisteredException::class, + 'withName', + array('foo') + ); + } +} diff --git a/tests/PHPExif/Exception/BaseExceptionTest.php b/tests/PHPExif/Exception/BaseExceptionTest.php new file mode 100644 index 0000000..ab23236 --- /dev/null +++ b/tests/PHPExif/Exception/BaseExceptionTest.php @@ -0,0 +1,41 @@ +assertInstanceOf( + $classname, + $result + ); + } +} diff --git a/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php b/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php new file mode 100644 index 0000000..75408b2 --- /dev/null +++ b/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php @@ -0,0 +1,25 @@ + + */ +class ElementAlreadyExistsExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers \PHPExif\Exception\Collection\ElementAlreadyExistsException::withKey + */ + public function testWithKeyReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + ElementAlreadyExistsException::class, + 'withKey', + array('foo') + ); + } +} diff --git a/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php b/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php new file mode 100644 index 0000000..83641b7 --- /dev/null +++ b/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php @@ -0,0 +1,25 @@ + + */ +class ElementNotExistsExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers \PHPExif\Exception\Collection\ElementNotExistsException::withKey + */ + public function testWithKeyReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + ElementNotExistsException::class, + 'withKey', + array('foo') + ); + } +} diff --git a/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php b/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php new file mode 100644 index 0000000..b1adfc0 --- /dev/null +++ b/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php @@ -0,0 +1,25 @@ + + */ +class InvalidElementTypeExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers \PHPExif\Exception\Collection\InvalidElementTypeException::withExpectedType + */ + public function testWithKeyReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + InvalidElementTypeException::class, + 'withExpectedType', + array('foo') + ); + } +} diff --git a/tests/PHPExif/Exception/NoExifDataExceptionTest.php b/tests/PHPExif/Exception/NoExifDataExceptionTest.php index 868e41f..326ff21 100644 --- a/tests/PHPExif/Exception/NoExifDataExceptionTest.php +++ b/tests/PHPExif/Exception/NoExifDataExceptionTest.php @@ -1,10 +1,14 @@ */ -class NoExifDataExceptionTest extends \PHPUnit_Framework_TestCase +class NoExifDataExceptionTest extends BaseExceptionTest { /** * @group exception @@ -12,11 +16,10 @@ class NoExifDataExceptionTest extends \PHPUnit_Framework_TestCase */ public function testFromFileReturnsInstance() { - $instance = NoExifDataException::fromFile('foo'); - - $this->assertInstanceOf( - '\\PHPExif\\Exception\\NoExifDataException', - $instance + $this->assertNamedConstructorReturnsInstance( + NoExifDataException::class, + 'fromFile', + array('foo') ); } } diff --git a/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php index 81489b2..dc72581 100644 --- a/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php +++ b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php @@ -1,10 +1,14 @@ */ -class UnknownAdapterTypeExceptionTest extends \PHPUnit_Framework_TestCase +class UnknownAdapterTypeExceptionTest extends BaseExceptionTest { /** * @group exception @@ -12,11 +16,10 @@ class UnknownAdapterTypeExceptionTest extends \PHPUnit_Framework_TestCase */ public function testForTypeReturnsInstance() { - $instance = UnknownAdapterTypeException::forType('foo'); - - $this->assertInstanceOf( - '\\PHPExif\\Exception\\UnknownAdapterTypeException', - $instance + $this->assertNamedConstructorReturnsInstance( + UnknownAdapterTypeException::class, + 'forType', + array('foo') ); } @@ -26,14 +29,10 @@ public function testForTypeReturnsInstance() */ public function testnoInterfaceReturnsInstance() { - $instance = UnknownAdapterTypeException::noInterface( - 'foo', - 'bar' - ); - - $this->assertInstanceOf( - '\\PHPExif\\Exception\\UnknownAdapterTypeException', - $instance + $this->assertNamedConstructorReturnsInstance( + UnknownAdapterTypeException::class, + 'noInterface', + array('foo', 'bar',) ); } } From 931ee7788ac3799238c957e2b37623ac67aa7bb6 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 28 Feb 2016 20:57:49 +0100 Subject: [PATCH 23/51] Removed older PHP versions from TravisCI build matrix Signed-off-by: Tom Van Herreweghe --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d126f4f..9f6cf72 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: php php: - - 5.3 - - 5.4 - - 5.5 - 5.6 - 7.0 From 0e3e7719aec34befe5e56b4f6f044a8217ad62dc Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 28 Feb 2016 21:00:10 +0100 Subject: [PATCH 24/51] Added PHP 7.0 as supported PHP requirement Signed-off-by: Tom Van Herreweghe --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 84f91eb..aedb0c9 100755 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ ], "keywords": ["EXIF", "IPTC", "jpeg", "tiff", "exiftool"], "require": { - "php": "~5.6.0" + "php": "~5.6.0 || ~7.0" }, "require-dev": { "phpmd/phpmd": "~2.3.0", From f19e49257961223abc2dac0e0aa7121618684c57 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 28 Feb 2016 21:06:56 +0100 Subject: [PATCH 25/51] Fixed travis configuration Signed-off-by: Tom Van Herreweghe --- .travis.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9f6cf72..45c15fe 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,16 @@ language: php -php: - - 5.6 - - 7.0 - -#matrix: -# allow_failures: -# - php: 5.6 +matrix: + fast_finish: true + include: + - php: 5.6 + - php: 7.0 script: - mkdir -p build/logs - php vendor/bin/phpunit -c phpunit.xml.dist - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml - - ./vendor/bin/phpcs --standard=PSR2 ./lib/ + - ./vendor/bin/phpcs --standard=PSR2 ./src/ before_script: - composer install --prefer-source From 36ff1fcacab4009ef91680ea06842c13121fe9ca Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 28 Feb 2016 21:08:21 +0100 Subject: [PATCH 26/51] Fixed composer config Signed-off-by: Tom Van Herreweghe --- composer.json | 2 +- composer.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index aedb0c9..e2fdc50 100755 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ ], "keywords": ["EXIF", "IPTC", "jpeg", "tiff", "exiftool"], "require": { - "php": "~5.6.0 || ~7.0" + "php": "^5.6 || ^7.0" }, "require-dev": { "phpmd/phpmd": "~2.3.0", diff --git a/composer.lock b/composer.lock index f2d4361..ed18561 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f32e7a7ee745431574de2977b839b9d3", - "content-hash": "6d2ad1edf1104b827e3d00d343188e8c", + "hash": "74a9535abeda5efbe331027573d7d666", + "content-hash": "22ebb18066da07f1f0a05654f59c8e8a", "packages": [], "packages-dev": [ { @@ -1880,7 +1880,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~5.6.0" + "php": "^5.6 || ^7.0" }, "platform-dev": [] } From 7e3b1678992634b5eb7fe684bd371dd768efacca Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 29 Feb 2016 21:03:51 +0100 Subject: [PATCH 27/51] HasMapper interface & MapperAccessorTrait implemented Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/AdapterConfig.php | 6 +++ src/PHPExif/Adapter/HasMapper.php | 40 +++++++++++++++ src/PHPExif/Adapter/MapperAccessorTrait.php | 48 +++++++++++++++++ .../Adapter/Native/NativeAdapterConfig.php | 6 ++- src/PHPExif/Adapter/Native/Reader.php | 36 ++----------- src/PHPExif/Adapter/WriterInterface.php | 51 +++++++++++++++++++ .../Adapter/NoMapperSetException.php | 22 ++++++++ 7 files changed, 177 insertions(+), 32 deletions(-) create mode 100644 src/PHPExif/Adapter/HasMapper.php create mode 100644 src/PHPExif/Adapter/MapperAccessorTrait.php create mode 100644 src/PHPExif/Adapter/WriterInterface.php create mode 100644 src/PHPExif/Exception/Adapter/NoMapperSetException.php diff --git a/src/PHPExif/Adapter/AdapterConfig.php b/src/PHPExif/Adapter/AdapterConfig.php index c738f93..d39daec 100644 --- a/src/PHPExif/Adapter/AdapterConfig.php +++ b/src/PHPExif/Adapter/AdapterConfig.php @@ -25,5 +25,11 @@ interface AdapterConfig const READER = 'reader'; const WRITER = 'writer'; + /** + * Factory method for producting the Reader/Writer + * + * @param string $type + * @return ReaderInterface|WriterInterface + */ public function factory($type); } diff --git a/src/PHPExif/Adapter/HasMapper.php b/src/PHPExif/Adapter/HasMapper.php new file mode 100644 index 0000000..71b2ce5 --- /dev/null +++ b/src/PHPExif/Adapter/HasMapper.php @@ -0,0 +1,40 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter; + +/** + * HasMapper + * + * Defines a public API for a accessing the mapper + * + * @category PHPExif + * @package Adapter + */ +interface HasMapper +{ + /** + * Accessor for the data mapper + * + * @return MapperInterface + */ + public function getMapper(); + + /** + * Mutator for the data mapper + * + * @param MapperInterface $mapper + * + * @return void + */ + public function setMapper(MapperInterface $mapper); +} diff --git a/src/PHPExif/Adapter/MapperAccessorTrait.php b/src/PHPExif/Adapter/MapperAccessorTrait.php new file mode 100644 index 0000000..45f9909 --- /dev/null +++ b/src/PHPExif/Adapter/MapperAccessorTrait.php @@ -0,0 +1,48 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + */ + +namespace PHPExif\Adapter; + +use PHPExif\Exception\Adapter\NoMapperSetException; + +/** + * MapperAccessorTrait + * + * @category PHPExif + * @package Adapter + */ +trait MapperAccessorTrait +{ + /** + * @var MapperInterface + */ + private $mapper; + + /** + * {@inheritDoc} + */ + public function getMapper() + { + if (null !== $this->mapper) { + return $this->mapper; + } + + throw new NoAdapterSetException; + } + + /** + * {@inheritDoc} + */ + public function setMapper(MapperInterface $mapper) + { + $this->mapper = $mapper; + } +} diff --git a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php index 2b9ebba..24a9258 100644 --- a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php +++ b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php @@ -12,6 +12,7 @@ namespace PHPExif\Adapter\Native; use PHPExif\Adapter\AdapterConfig; +use PHPExif\Adapter\HasMapper; use PHPExif\Adapter\Native\Reader; use PHPExif\Adapter\Native\ReaderConfig; @@ -21,10 +22,13 @@ * @category PHPExif * @package Adapter */ -final class NativeAdapterConfig implements AdapterConfig +final class NativeAdapterConfig implements AdapterConfig, HasMapper { + use MapperAccessorTrait; + const ENABLE = true; const DISABLE = false; + /** * @var array */ diff --git a/src/PHPExif/Adapter/Native/Reader.php b/src/PHPExif/Adapter/Native/Reader.php index 0f7df6f..490b8d9 100644 --- a/src/PHPExif/Adapter/Native/Reader.php +++ b/src/PHPExif/Adapter/Native/Reader.php @@ -12,7 +12,8 @@ namespace PHPExif\Adapter\Native; -use PHPExif\Adapter\MapperInterface; +use PHPExif\Adapter\HasMapper; +use PHPExif\Adapter\MapperAccessorTrait; use PHPExif\Adapter\ReaderInterface; use PHPExif\Exception\NoExifDataException; use PHPExif\Exception\UnknownAdapterTypeException; @@ -23,18 +24,15 @@ * @category PHPExif * @package Adapter */ -final class Reader implements ReaderInterface +final class Reader implements ReaderInterface, HasMapper { + use MapperAccessorTrait; + /** * @var ReaderConfig */ private $configuration; - /** - * @var MapperInterface - */ - private $mapper; - /** * @param ReaderConfig $configuration */ @@ -43,30 +41,6 @@ public function __construct(ReaderConfig $configuration) $this->configuration = $configuration; } - /** - * {@inheritDoc} - */ - public function getMapper() - { - if (null !== $this->mapper) { - return $this->mapper; - } - - $this->setMapper( - new Mapper - ); - - return $this->mapper; - } - - /** - * {@inheritDoc} - */ - public function setMapper(MapperInterface $mapper) - { - $this->mapper = $mapper; - } - /** * {@inheritDoc} * diff --git a/src/PHPExif/Adapter/WriterInterface.php b/src/PHPExif/Adapter/WriterInterface.php new file mode 100644 index 0000000..ee0c2c2 --- /dev/null +++ b/src/PHPExif/Adapter/WriterInterface.php @@ -0,0 +1,51 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Adapter; + +use PHPExif\Data\MetadataInterface; + +/** + * WriterInterface + * + * Public API for writing EXIF data + * + * @category PHPExif + * @package Exif + */ +interface WriterInterface +{ + /** + * Accessor for the data mapper + * + * @return MapperInterface + */ + public function getMapper(); + + /** + * Mutator for the data mapper + * + * @param MapperInterface $mapper + * + * @return void + */ + public function setMapper(MapperInterface $mapper); + + /** + * Read the available metadata of given file + * + * @param string $filePath + * @param MetadataInterface $metadata + * + * @return MetadataInterface + */ + public function writeMetadataToFile($filePath, MetadataInterface $metadata); +} diff --git a/src/PHPExif/Exception/Adapter/NoMapperSetException.php b/src/PHPExif/Exception/Adapter/NoMapperSetException.php new file mode 100644 index 0000000..288bfc1 --- /dev/null +++ b/src/PHPExif/Exception/Adapter/NoMapperSetException.php @@ -0,0 +1,22 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exception + */ + +namespace PHPExif\Exception\Adapter; + +/** + * NoMapperSetException + * + * @category PHPExif + * @package Exception + */ +class NoMapperSetException extends \RuntimeException +{ +} From fc2f2a4c15b39b2cf3dd0c51a2a2532cd9537463 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 29 Feb 2016 21:10:22 +0100 Subject: [PATCH 28/51] Reader requires MapperInterface when creating new instance Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/NativeAdapterConfig.php | 3 ++- src/PHPExif/Adapter/Native/Reader.php | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php index 24a9258..357a476 100644 --- a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php +++ b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php @@ -96,7 +96,8 @@ private function getReader() $reader = new Reader( ReaderConfig::fromArray( $this->config[AdapterConfig::READER] - ) + ), + $this->getMapper() ); return $reader; diff --git a/src/PHPExif/Adapter/Native/Reader.php b/src/PHPExif/Adapter/Native/Reader.php index 490b8d9..38e80e2 100644 --- a/src/PHPExif/Adapter/Native/Reader.php +++ b/src/PHPExif/Adapter/Native/Reader.php @@ -14,6 +14,7 @@ use PHPExif\Adapter\HasMapper; use PHPExif\Adapter\MapperAccessorTrait; +use PHPExif\Adapter\MapperInterface; use PHPExif\Adapter\ReaderInterface; use PHPExif\Exception\NoExifDataException; use PHPExif\Exception\UnknownAdapterTypeException; @@ -36,9 +37,12 @@ final class Reader implements ReaderInterface, HasMapper /** * @param ReaderConfig $configuration */ - public function __construct(ReaderConfig $configuration) - { + public function __construct( + ReaderConfig $configuration, + MapperInterface $mapper + ) { $this->configuration = $configuration; + $this->setMapper($mapper); } /** From 2cb901288eb01e6abd3d1304f45a21398b991fbf Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 29 Feb 2016 22:27:00 +0100 Subject: [PATCH 29/51] ArrayMapper & FieldMapper interfaces Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/ArrayMapper.php | 64 ++++++++++++++++++++++ src/PHPExif/Adapter/Native/FieldMapper.php | 45 +++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/PHPExif/Adapter/Native/ArrayMapper.php create mode 100644 src/PHPExif/Adapter/Native/FieldMapper.php diff --git a/src/PHPExif/Adapter/Native/ArrayMapper.php b/src/PHPExif/Adapter/Native/ArrayMapper.php new file mode 100644 index 0000000..bd4d721 --- /dev/null +++ b/src/PHPExif/Adapter/Native/ArrayMapper.php @@ -0,0 +1,64 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Mapper + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native; + +use PHPExif\Adapter\Native\Exception\MapperNotRegisteredException; + +/** + * ArrayMapper + * + * Public API for mapping an array of EXIF data + * to and from Exif + * + * @category PHPExif + * @package Mapper + */ +interface ArrayMapper +{ + /** + * Register given list of FieldMapper instances + * + * @param FieldMapper[]|array $fieldMappers + * @return void + */ + public function registerFieldMappers(array $fieldMappers); + + /** + * Determines if a mapper is registered for given field + * + * @param string $field + * @return bool + */ + public function mapperRegisteredForField($field); + + /** + * Returns the mapper associated with given field + * + * @param string $field + * + * @throws MapperNotRegisteredException when no mapper is registered for given field + * + * @return FieldMapper + */ + public function getFieldMapper($field); + + /** + * Maps given input on given output + * + * @param array $input + * @param object $output + * + * @return void + */ + public function mapArray(array $input, $output); +} diff --git a/src/PHPExif/Adapter/Native/FieldMapper.php b/src/PHPExif/Adapter/Native/FieldMapper.php new file mode 100644 index 0000000..ab99edf --- /dev/null +++ b/src/PHPExif/Adapter/Native/FieldMapper.php @@ -0,0 +1,45 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Mapper + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native; + +use PHPExif\Data\MetadataInterface; + +/** + * FieldMapper + * + * Public API for mapping fields of EXIF data + * to and from Exif + * + * @category PHPExif + * @package Mapper + */ +interface FieldMapper +{ + /** + * Returns a list of fields this instance knows how to map + * + * @return array + */ + public function getSupportedFields(); + + /** + * Map given $field from given input to given output + * + * @param string $field + * @param aray $input + * @param object $output + * + * @return void + */ + public function mapField($field, array $input, &$output); +} From e873e5e872bc23c65666938d82632bc8b2d0d481 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 29 Feb 2016 22:27:27 +0100 Subject: [PATCH 30/51] Trait which implements ArrayMapper methods Signed-off-by: Tom Van Herreweghe --- .../Adapter/Native/FieldMapperTrait.php | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/PHPExif/Adapter/Native/FieldMapperTrait.php diff --git a/src/PHPExif/Adapter/Native/FieldMapperTrait.php b/src/PHPExif/Adapter/Native/FieldMapperTrait.php new file mode 100644 index 0000000..03cd7fa --- /dev/null +++ b/src/PHPExif/Adapter/Native/FieldMapperTrait.php @@ -0,0 +1,76 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native; + +use PHPExif\Adapter\Native\Exception\MapperNotRegisteredException; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +trait FieldMapperTrait +{ + /** + * @var FieldMapper[] + */ + private $fieldMappers = array(); + + /** + * {@inheritDoc} + */ + public function registerFieldMappers(array $fieldMappers) + { + foreach ($fieldMappers as $fieldMapper) { + $this->registerFieldMapper($fieldMapper); + } + } + + /** + * Registers given FieldMapper instance + * + * @param FieldMapper $fieldMapper + * + * @return void + */ + public function registerFieldMapper(FieldMapper $fieldMapper) + { + $targetFields = $fieldMapper->getSupportedFields(); + + foreach ($targetFields as $fieldName) { + // explicitly allow overwriting the FieldMapper for a given field + $this->fieldMappers[$fieldName] = $fieldMapper; + } + } + + /** + * {@inheritDoc} + */ + public function getFieldMapper($field) + { + if (!$this->mapperRegisteredForField($field)) { + throw MapperNotRegisteredException::forField($field); + } + + return $this->fieldMappers[$field]; + } + + /** + * {@inheritDoc} + */ + public function mapperRegisteredForField($field) + { + return array_key_exists($field, $this->fieldMappers); + } +} From 32d2a0b28facd57d19fc5b08f7de300b5d7a3b76 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 29 Feb 2016 22:27:50 +0100 Subject: [PATCH 31/51] Mapper for MetaData, Exif & Iptc: basic implementation Signed-off-by: Tom Van Herreweghe --- .../MapperNotRegisteredException.php | 38 ++ .../Exception/UnsupportedOutputException.php | 38 ++ src/PHPExif/Adapter/Native/Mapper.php | 365 ++---------------- .../Mapper/Exif/ApertureFieldMapper.php | 48 +++ .../Exif/GuardInvalidArgumentsTrait.php | 49 +++ .../Adapter/Native/Mapper/ExifMapper.php | 51 +++ .../Adapter/Native/Mapper/IptcMapper.php | 51 +++ 7 files changed, 297 insertions(+), 343 deletions(-) create mode 100644 src/PHPExif/Adapter/Native/Exception/MapperNotRegisteredException.php create mode 100644 src/PHPExif/Adapter/Native/Exception/UnsupportedOutputException.php create mode 100644 src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php create mode 100644 src/PHPExif/Adapter/Native/Mapper/Exif/GuardInvalidArgumentsTrait.php create mode 100644 src/PHPExif/Adapter/Native/Mapper/ExifMapper.php create mode 100644 src/PHPExif/Adapter/Native/Mapper/IptcMapper.php diff --git a/src/PHPExif/Adapter/Native/Exception/MapperNotRegisteredException.php b/src/PHPExif/Adapter/Native/Exception/MapperNotRegisteredException.php new file mode 100644 index 0000000..95e6dc2 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Exception/MapperNotRegisteredException.php @@ -0,0 +1,38 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native\Exception; + +/** + * MapperNotRegisteredException + * + * @category PHPExif + * @package Adapter + */ +class MapperNotRegisteredException extends \Exception +{ + /** + * Returns new instance with set message + * + * @param string $field + * @return MapperNotRegisteredException + */ + public static function forField($field) + { + return new self( + sprintf( + 'No mapper was registered for field "%1$s"', + $field + ) + ); + } +} diff --git a/src/PHPExif/Adapter/Native/Exception/UnsupportedOutputException.php b/src/PHPExif/Adapter/Native/Exception/UnsupportedOutputException.php new file mode 100644 index 0000000..4c9c6ce --- /dev/null +++ b/src/PHPExif/Adapter/Native/Exception/UnsupportedOutputException.php @@ -0,0 +1,38 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native\Exception; + +/** + * UnsupportedOutputException + * + * @category PHPExif + * @package Adapter + */ +class UnsupportedOutputException extends \Exception +{ + /** + * Returns new instance with set message + * + * @param object $output + * @return UnsupportedOutputException + */ + public static function forOutput($output) + { + return new self( + sprintf( + 'Mapper does not support output objects of type "%1$s"', + get_class($output) + ) + ); + } +} diff --git a/src/PHPExif/Adapter/Native/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php index 2efe289..ed62c00 100644 --- a/src/PHPExif/Adapter/Native/Mapper.php +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -1,377 +1,56 @@ + * @copyright Copyright (c) 2015 Tom Van Herreweghe * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Exif + * @package Adapter + * @codeCoverageIgnore */ namespace PHPExif\Adapter\Native; -use PHPExif\Adapter\MapperInterface; -use PHPExif\Data\Exif; -use PHPExif\Data\ExifInterface; -use PHPExif\Exception\InterruptException; +use PHPExif\Adapter\Native\Exception\MapperNotRegisteredException; +use PHPExif\Data\MetaData; /** - * Mapper class + * Mapper * * @category PHPExif - * @package Exif + * @package Adapter */ -final class Mapper implements MapperInterface +class Mapper implements MapperInterface, ArrayMapper { - const APERTUREFNUMBER = 'ApertureFNumber'; - const ARTIST = 'Artist'; - const CAPTION = 'caption'; - const COLORSPACE = 'ColorSpace'; - const COPYRIGHT = 'copyright'; - const CREDIT = 'credit'; - const DATETIMEORIGINAL = 'DateTimeOriginal'; - const EXPOSURETIME = 'ExposureTime'; - const FILESIZE = 'FileSize'; - const FOCALLENGTH = 'FocalLength'; - const FOCUSDISTANCE = 'FocusDistance'; - const GPSLATITUDE = 'GPSLatitude'; - const GPSLONGITUDE = 'GPSLongitude'; - const HEADLINE = 'headline'; - const HEIGHT = 'Height'; - const ISOSPEEDRATINGS = 'ISOSpeedRatings'; - const JOBTITLE = 'jobtitle'; - const KEYWORDS = 'keywords'; - const MIMETYPE = 'MimeType'; - const MODEL = 'Model'; - const ORIENTATION = 'Orientation'; - const SOFTWARE = 'Software'; - const SOURCE = 'source'; - const TITLE = 'title'; - const WIDTH = 'Width'; - const XRESOLUTION = 'XResolution'; - const YRESOLUTION = 'YResolution'; + use FieldMapperTrait; - const SECTION_COMMENT = 'COMMENT'; - const SECTION_COMPUTED = 'COMPUTED'; - const SECTION_EXIF = 'EXIF'; - const SECTION_FILE = 'FILE'; - const SECTION_IFD0 = 'IFD0'; - const SECTION_IPTC = 'IPTC'; - const SECTION_THUMBNAIL = 'THUMBNAIL'; - - /** - * A list of section names - * - * @var array - */ - private $sections = array( - self::SECTION_COMMENT, - self::SECTION_COMPUTED, - self::SECTION_EXIF, - self::SECTION_FILE, - self::SECTION_IFD0, - self::SECTION_IPTC, - self::SECTION_THUMBNAIL, - ); - - /** - * Maps the native fields to the fields of - * the \PHPExif\Data\Exif class - * - * @var array - */ - private $map = array( - self::APERTUREFNUMBER => ExifInterface::APERTURE, - self::ARTIST => ExifInterface::AUTHOR, - self::CAPTION => ExifInterface::CAPTION, - self::COLORSPACE => ExifInterface::COLORSPACE, - self::COPYRIGHT => ExifInterface::COPYRIGHT, - self::CREDIT => ExifInterface::CREDIT, - self::DATETIMEORIGINAL => ExifInterface::CREATION_DATE, - self::EXPOSURETIME => ExifInterface::EXPOSURE, - self::FILESIZE => ExifInterface::FILESIZE, - self::FOCALLENGTH => ExifInterface::FOCAL_LENGTH, - self::FOCUSDISTANCE => ExifInterface::FOCAL_DISTANCE, - self::GPSLATITUDE => ExifInterface::GPS, - self::GPSLONGITUDE => ExifInterface::GPS, - self::HEADLINE => ExifInterface::HEADLINE, - self::HEIGHT => ExifInterface::HEIGHT, - self::ISOSPEEDRATINGS => ExifInterface::ISO, - self::JOBTITLE => ExifInterface::JOB_TITLE, - self::KEYWORDS => ExifInterface::KEYWORDS, - self::MIMETYPE => ExifInterface::MIMETYPE, - self::MODEL => ExifInterface::CAMERA, - self::ORIENTATION => ExifInterface::ORIENTATION, - self::SOFTWARE => ExifInterface::SOFTWARE, - self::SOURCE => ExifInterface::SOURCE, - self::TITLE => ExifInterface::TITLE, - self::WIDTH => ExifInterface::WIDTH, - self::XRESOLUTION => ExifInterface::HORIZONTAL_RESOLUTION, - self::YRESOLUTION => ExifInterface::VERTICAL_RESOLUTION, - ); - - /** - * Maps a Native field to a method to manipulate the data - * for the \PHPExif\Data\Exif class - * - * @var array - */ - private $manipulators = array( - self::DATETIMEORIGINAL => 'convertDateTimeOriginal', - self::EXPOSURETIME => 'convertExposureTime', - self::FOCALLENGTH => 'convertFocalLength', - self::GPSLATITUDE => 'extractGPSCoordinate', - self::GPSLONGITUDE => 'extractGPSCoordinate', - self::XRESOLUTION => 'convertResolution', - self::YRESOLUTION => 'convertResolution', - ); + const FIELD_EXIF = 'exif'; + const FIELD_IPTC = 'iptc'; /** * {@inheritDoc} */ public function map(array $data) { - $mappedData = array(); - foreach ($data as $field => $value) { - try { - $this->handleSection($field, $value, $mappedData); - $this->skipUnknownField($field); - $this->doCustomManipulation($field, $value); - } catch (InterruptException $e) { - continue; - } - - // set end result - $key = $this->map[$field]; - $mappedData[$key] = $value; - } - - $mappedData = $this->mapGPSData($data, $mappedData); + $output = new Metadata; - $exif = new Exif($mappedData); + $this->mapArray($data, $output); - return $exif; + return $output; } /** * {@inheritDoc} */ - public function serialize(ExifInterface $exif) - { - } - - /** - * Maps section data and merges it into the list of mapped data - * - * @param string $field - * @param string $value - * @param array $mappedData - * @throws InterruptException - */ - private function handleSection($field, $value, array &$mappedData) - { - if (!($this->isSection($field) && is_array($value))) { - return; - } - - $subData = $this->map($value); - $mappedData = array_merge( - $mappedData, - $subData - ); - - throw new InterruptException(); - } - - /** - * Determines if given field is known for mapping - * - * @param string $field - * @throws InterruptException - */ - private function skipUnknownField($field) + public function mapArray(array $input, $output) { - if (array_key_exists($field, $this->map)) { - return; - } - - throw new InterruptException(); - } - - /** - * Executes the custom manipulators if necessary - * - * @param string $field - * @param mixed $value - * @throws InterruptException - */ - private function doCustomManipulation($field, &$value) - { - if (!array_key_exists($field, $this->manipulators)) { - return; - } - - $method = $this->manipulators[$field]; - $value = $this->$method($value); - - if (null === $value) { - throw new InterruptException(); - } - } - - /** - * Maps GPS data to the correct key, if such data exists - * - * @param array $data - * @param array $mappedData - * @return array - */ - private function mapGPSData(array $data, array $mappedData) - { - if (!array_key_exists(self::GPSLATITUDE, $mappedData)) { - return $mappedData; - } - $gpsLocation = sprintf( - '%s,%s', - (strtoupper($data['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $mappedData[self::GPSLATITUDE], - (strtoupper($data['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $mappedData[self::GPSLONGITUDE] - ); - unset($mappedData[self::GPSLATITUDE]); - unset($mappedData[self::GPSLONGITUDE]); - $mappedData[Exif::GPS] = $gpsLocation; - return $mappedData; - } - - /** - * Determines if given field is a section - * - * @param string $field - * @return bool - */ - private function isSection($field) - { - return (in_array($field, $this->sections)); - } - - /** - * Converts incoming Native date to a DateTime object - * - * @param string $originalValue - * @return \DateTime - */ - private function convertDateTimeOriginal($originalValue) - { - try { - $originalValue = new DateTime($originalValue); - } catch (Exception $exception) { - return; - } - - return $originalValue; - } - - /** - * Converts incoming exposure time to a sensible format - * - * @param string $originalValue - * @return string - */ - private function convertExposureTime($originalValue) - { - if (!is_float($originalValue)) { - $originalValue = $this->normalizeComponent($value); - } - - // Based on the source code of Exiftool (PrintExposureTime subroutine): - // http://cpansearch.perl.org/src/EXIFTOOL/Image-ExifTool-9.90/lib/Image/ExifTool/Exif.pm - if ($originalValue < 0.25001 && $originalValue > 0) { - return sprintf( - '1/%d', - intval(0.5 + 1 / $originalValue) - ); - } - - $originalValue = sprintf('%.1f', $originalValue); - return preg_replace('/.0$/', '', $originalValue); - } - - /** - * Converts focal length to a float value - * - * @param string $originalValue - * @return float - */ - private function convertFocalLength($originalValue) - { - $parts = explode('/', $originalValue); - return ((int) reset($parts) / (int) end($parts)); - } - - /** - * Converts incoming resolution value to a sensible value - * - * @param string $originalValue - * @return int - */ - private function convertResolution($originalValue) - { - $resolutionParts = explode('/', $originalValue); - return ((int) reset($resolutionParts)); - } - - /** - * Extract GPS coordinates from components array - * - * @param array $components - * @return float - */ - private function extractGPSCoordinate(array $components) - { - $components = array_map( - array($this, 'normalizeGPSComponent'), - $components - ); - - if (count($components) > 2) { - return intval($components[0]) + (intval($components[1]) / 60) + (floatval($components[2]) / 3600); - } - - return reset($components); - } - - /** - * Normalize GPS coordinates components - * - * @param mixed $component - * @return int|float - */ - private function normalizeGPSComponent($component) - { - $parts = explode('/', $component); - return count($parts) === 1 ? $parts[0] : (int) reset($parts) / (int) end($parts); - } - - /** - * Normalize component - * - * @param mixed $component - * @return int|float - */ - private function normalizeComponent($component) - { - $parts = explode('/', $component); - - if (count($parts) > 1) { - if ($parts[1]) { - return intval($parts[0]) / intval($parts[1]); - } - - return 0; - } + $exif = $output->getExif(); + $exifMapper = $this->getFieldMapper(self::FIELD_EXIF); + $exifMapper->mapArray($input, $exif); - return floatval(reset($parts)); + $iptc = $output->getIptc(); + $iptcMapper = $this->getFieldMapper(self::FIELD_IPTC); + $iptcMapper->mapArray($input, $iptc); } } diff --git a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php new file mode 100644 index 0000000..6bf1ef0 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php @@ -0,0 +1,48 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native\Mapper\Exif; + +use PHPExif\Adapter\Native\Exception\UnsupportedFieldException; +use PHPExif\Adapter\Native\FieldMapper; +use PHPExif\Data\ExifInterface; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +class ApertureFieldMapper implements FieldMapper +{ + use GuardInvalidArgumentsTrait; + + /** + * {@inheritDoc} + */ + public function getSupportedFields() + { + return array( + ExifInterface::APERTURE, + ); + } + + /** + * {@inheritDoc} + */ + public function mapField($field, array $input, &$output) + { + $this->guardInvalidArguments($field, $input, $output); + + $output = $output->withAperture($input['ApertureFNumber']); + } +} diff --git a/src/PHPExif/Adapter/Native/Mapper/Exif/GuardInvalidArgumentsTrait.php b/src/PHPExif/Adapter/Native/Mapper/Exif/GuardInvalidArgumentsTrait.php new file mode 100644 index 0000000..636b6a9 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper/Exif/GuardInvalidArgumentsTrait.php @@ -0,0 +1,49 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native\Mapper\Exif; + +use PHPExif\Adapter\Native\Exception\UnsupportedFieldException; +use PHPExif\Adapter\Native\Exception\UnsupportedOutputException; +use PHPExif\Data\ExifInterface; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +trait GuardInvalidArgumentsTrait +{ + /** + * Guard function for invalid arguments + * + * @param string $field + * @param array $input + * @param object $output + * + * @throws UnsupportedFieldException when asked to map an unsupported field + * @throws UnsupportedOutputException when asked to map data on an unsupported output object + * + * @return void + */ + private function guardInvalidArguments($field, array $input, $output) + { + if (!in_array($field, $this->getSupportedFields())) { + throw UnsupportedFieldException::forField($field); + } + + if (!($output instanceof ExifInterface)) { + throw UnsupportedOutputException::forOutput($output); + } + } +} diff --git a/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php b/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php new file mode 100644 index 0000000..eb2ca15 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php @@ -0,0 +1,51 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native\Mapper; + +use PHPExif\Adapter\Native\Exception\UnsupportedOutputException; +use PHPExif\Adapter\Native\FieldMapperTrait; +use PHPExif\Data\ExifInterface; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +class ExifMapper implements ArrayMapper +{ + use FieldMapperTrait; + + /** + * {@inheritDoc} + */ + public function mapArray(array $input, $output) + { + if (!($output instanceof ExifInterface)) { + throw UnsupportedOutputException::forOutput($output); + } + + $data = $output->toArray(true); + $fields = array_keys($data); + + foreach ($fields as $name) { + $fieldMapper = $this->getFieldMapper($name); + + $fieldMapper->mapField( + $name, + $input, + $output + ); + } + } +} diff --git a/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php b/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php new file mode 100644 index 0000000..9c5a85a --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php @@ -0,0 +1,51 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native\Mapper; + +use PHPExif\Adapter\Native\Exception\UnsupportedOutputException; +use PHPExif\Adapter\Native\FieldMapperTrait; +use PHPExif\Data\IptcInterface; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +class IptcMapper implements ArrayMapper +{ + use FieldMapperTrait; + + /** + * {@inheritDoc} + */ + public function mapArray(array $input, $output) + { + if (!($output instanceof IptcInterface)) { + throw UnsupportedOutputException::forOutput($output); + } + + $data = $output->toArray(true); + $fields = array_keys($data); + + foreach ($fields as $name) { + $fieldMapper = $this->getFieldMapper($name); + + $fieldMapper->mapField( + $name, + $input, + $output + ); + } + } +} From bde0bd4a85c6b8303188bf5b7447698737cbe94a Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 29 Feb 2016 22:36:20 +0100 Subject: [PATCH 32/51] Defined & implemented methods for Aperture access on Exif object Signed-off-by: Tom Van Herreweghe --- .../Mapper/Exif/ApertureFieldMapper.php | 2 +- src/PHPExif/Data/Exif.php | 21 +++++++++++++++++-- src/PHPExif/Data/ExifInterface.php | 16 ++++++++++++++ src/PHPExif/Data/Metadata.php | 2 +- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php index 6bf1ef0..7997c12 100644 --- a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php @@ -43,6 +43,6 @@ public function mapField($field, array $input, &$output) { $this->guardInvalidArguments($field, $input, $output); - $output = $output->withAperture($input['ApertureFNumber']); + $output = $output->withAperture((float) $input['ApertureFNumber']); } } diff --git a/src/PHPExif/Data/Exif.php b/src/PHPExif/Data/Exif.php index 45b6803..5db42a2 100644 --- a/src/PHPExif/Data/Exif.php +++ b/src/PHPExif/Data/Exif.php @@ -22,9 +22,26 @@ final class Exif implements ExifInterface { /** - * @param array $rawData + * @var float */ - public function __construct(array $data) + private $aperture; + + /** + * {@inheritDoc} + */ + public function getAperture() { + return $this->aperture; + } + + /** + * {@inheritDoc} + */ + public function withAperture($aperture) + { + $new = clone $this; + $new->aperture = $aperture; + + return $new; } } diff --git a/src/PHPExif/Data/ExifInterface.php b/src/PHPExif/Data/ExifInterface.php index 9eaed65..a687c6a 100644 --- a/src/PHPExif/Data/ExifInterface.php +++ b/src/PHPExif/Data/ExifInterface.php @@ -47,4 +47,20 @@ interface ExifInterface const VERTICAL_RESOLUTION = 'verticalResolution'; const WIDTH = 'width'; const GPS = 'gps'; + + /** + * Accessor for the aperture + * + * @return float + */ + public function getAperture(); + + /** + * Returns new instance with updated aperture + * + * @param float $aperture + * + * @return ExifInterface + */ + public function withAperture($aperture); } diff --git a/src/PHPExif/Data/Metadata.php b/src/PHPExif/Data/Metadata.php index dcf39ac..e4cc10b 100644 --- a/src/PHPExif/Data/Metadata.php +++ b/src/PHPExif/Data/Metadata.php @@ -59,7 +59,7 @@ public function withIptc(IptcInterface $iptc) public function getExif() { if (null === $this->exif) { - $this->exif = new Exif(array()); + $this->exif = new Exif; } return $this->exif; From b015129d822ebf497d89d64ad127d9be9894e589 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 2 Mar 2016 19:30:23 +0100 Subject: [PATCH 33/51] Moved Mapper interfaces to non-adapter namespace + refactored implementations for this Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/Mapper.php | 4 +++- .../Adapter/Native/Mapper/Exif/ApertureFieldMapper.php | 3 +-- src/PHPExif/Adapter/Native/Mapper/ExifMapper.php | 5 +++-- src/PHPExif/Adapter/Native/Mapper/IptcMapper.php | 5 +++-- .../Mapper}/MapperNotRegisteredException.php | 6 +++--- .../Mapper}/UnsupportedOutputException.php | 6 +++--- src/PHPExif/{Adapter/Native => Mapper}/ArrayMapper.php | 8 ++++---- src/PHPExif/{Adapter/Native => Mapper}/FieldMapper.php | 8 ++++---- .../{Adapter/Native => Mapper}/FieldMapperTrait.php | 10 +++++----- 9 files changed, 29 insertions(+), 26 deletions(-) rename src/PHPExif/{Adapter/Native/Exception => Exception/Mapper}/MapperNotRegisteredException.php (90%) rename src/PHPExif/{Adapter/Native/Exception => Exception/Mapper}/UnsupportedOutputException.php (90%) rename src/PHPExif/{Adapter/Native => Mapper}/ArrayMapper.php (90%) rename src/PHPExif/{Adapter/Native => Mapper}/FieldMapper.php (86%) rename src/PHPExif/{Adapter/Native => Mapper}/FieldMapperTrait.php (87%) diff --git a/src/PHPExif/Adapter/Native/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php index ed62c00..401136e 100644 --- a/src/PHPExif/Adapter/Native/Mapper.php +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -12,8 +12,10 @@ namespace PHPExif\Adapter\Native; -use PHPExif\Adapter\Native\Exception\MapperNotRegisteredException; +use PHPExif\Adapter\MapperInterface; use PHPExif\Data\MetaData; +use PHPExif\Mapper\ArrayMapper; +use PHPExif\Mapper\FieldMapperTrait; /** * Mapper diff --git a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php index 7997c12..c51411b 100644 --- a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php @@ -12,9 +12,8 @@ namespace PHPExif\Adapter\Native\Mapper\Exif; -use PHPExif\Adapter\Native\Exception\UnsupportedFieldException; -use PHPExif\Adapter\Native\FieldMapper; use PHPExif\Data\ExifInterface; +use PHPExif\Mapper\FieldMapper; /** * Mapper diff --git a/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php b/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php index eb2ca15..9e5f03b 100644 --- a/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php @@ -12,9 +12,10 @@ namespace PHPExif\Adapter\Native\Mapper; -use PHPExif\Adapter\Native\Exception\UnsupportedOutputException; -use PHPExif\Adapter\Native\FieldMapperTrait; use PHPExif\Data\ExifInterface; +use PHPExif\Exception\Mapper\UnsupportedOutputException; +use PHPExif\Mapper\ArrayMapper; +use PHPExif\Mapper\FieldMapperTrait; /** * Mapper diff --git a/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php b/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php index 9c5a85a..80ae62a 100644 --- a/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php @@ -12,9 +12,10 @@ namespace PHPExif\Adapter\Native\Mapper; -use PHPExif\Adapter\Native\Exception\UnsupportedOutputException; -use PHPExif\Adapter\Native\FieldMapperTrait; use PHPExif\Data\IptcInterface; +use PHPExif\Exception\Mapper\UnsupportedOutputException; +use PHPExif\Mapper\ArrayMapper; +use PHPExif\Mapper\FieldMapperTrait; /** * Mapper diff --git a/src/PHPExif/Adapter/Native/Exception/MapperNotRegisteredException.php b/src/PHPExif/Exception/Mapper/MapperNotRegisteredException.php similarity index 90% rename from src/PHPExif/Adapter/Native/Exception/MapperNotRegisteredException.php rename to src/PHPExif/Exception/Mapper/MapperNotRegisteredException.php index 95e6dc2..0d41305 100644 --- a/src/PHPExif/Adapter/Native/Exception/MapperNotRegisteredException.php +++ b/src/PHPExif/Exception/Mapper/MapperNotRegisteredException.php @@ -6,17 +6,17 @@ * @copyright Copyright (c) 2015 Tom Van Herreweghe * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Adapter + * @package Exif * @codeCoverageIgnore */ -namespace PHPExif\Adapter\Native\Exception; +namespace PHPExif\Exception\Mapper; /** * MapperNotRegisteredException * * @category PHPExif - * @package Adapter + * @package Exif */ class MapperNotRegisteredException extends \Exception { diff --git a/src/PHPExif/Adapter/Native/Exception/UnsupportedOutputException.php b/src/PHPExif/Exception/Mapper/UnsupportedOutputException.php similarity index 90% rename from src/PHPExif/Adapter/Native/Exception/UnsupportedOutputException.php rename to src/PHPExif/Exception/Mapper/UnsupportedOutputException.php index 4c9c6ce..2dfabd4 100644 --- a/src/PHPExif/Adapter/Native/Exception/UnsupportedOutputException.php +++ b/src/PHPExif/Exception/Mapper/UnsupportedOutputException.php @@ -6,17 +6,17 @@ * @copyright Copyright (c) 2015 Tom Van Herreweghe * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Adapter + * @package Exif * @codeCoverageIgnore */ -namespace PHPExif\Adapter\Native\Exception; +namespace PHPExif\Exception\Mapper; /** * UnsupportedOutputException * * @category PHPExif - * @package Adapter + * @package Exif */ class UnsupportedOutputException extends \Exception { diff --git a/src/PHPExif/Adapter/Native/ArrayMapper.php b/src/PHPExif/Mapper/ArrayMapper.php similarity index 90% rename from src/PHPExif/Adapter/Native/ArrayMapper.php rename to src/PHPExif/Mapper/ArrayMapper.php index bd4d721..67e341a 100644 --- a/src/PHPExif/Adapter/Native/ArrayMapper.php +++ b/src/PHPExif/Mapper/ArrayMapper.php @@ -6,13 +6,13 @@ * @copyright Copyright (c) 2015 Tom Van Herreweghe * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Mapper + * @package Exif * @codeCoverageIgnore */ -namespace PHPExif\Adapter\Native; +namespace PHPExif\Mapper; -use PHPExif\Adapter\Native\Exception\MapperNotRegisteredException; +use PHPExif\Exception\Mapper\MapperNotRegisteredException; /** * ArrayMapper @@ -21,7 +21,7 @@ * to and from Exif * * @category PHPExif - * @package Mapper + * @package Exif */ interface ArrayMapper { diff --git a/src/PHPExif/Adapter/Native/FieldMapper.php b/src/PHPExif/Mapper/FieldMapper.php similarity index 86% rename from src/PHPExif/Adapter/Native/FieldMapper.php rename to src/PHPExif/Mapper/FieldMapper.php index ab99edf..f8ec2af 100644 --- a/src/PHPExif/Adapter/Native/FieldMapper.php +++ b/src/PHPExif/Mapper/FieldMapper.php @@ -6,11 +6,11 @@ * @copyright Copyright (c) 2015 Tom Van Herreweghe * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Mapper + * @package Exif * @codeCoverageIgnore */ -namespace PHPExif\Adapter\Native; +namespace PHPExif\Mapper; use PHPExif\Data\MetadataInterface; @@ -21,7 +21,7 @@ * to and from Exif * * @category PHPExif - * @package Mapper + * @package Exif */ interface FieldMapper { @@ -41,5 +41,5 @@ public function getSupportedFields(); * * @return void */ - public function mapField($field, array $input, &$output); + public function mapField($field, array $input, $output); } diff --git a/src/PHPExif/Adapter/Native/FieldMapperTrait.php b/src/PHPExif/Mapper/FieldMapperTrait.php similarity index 87% rename from src/PHPExif/Adapter/Native/FieldMapperTrait.php rename to src/PHPExif/Mapper/FieldMapperTrait.php index 03cd7fa..d38429a 100644 --- a/src/PHPExif/Adapter/Native/FieldMapperTrait.php +++ b/src/PHPExif/Mapper/FieldMapperTrait.php @@ -6,19 +6,19 @@ * @copyright Copyright (c) 2015 Tom Van Herreweghe * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Adapter + * @package Exif * @codeCoverageIgnore */ -namespace PHPExif\Adapter\Native; +namespace PHPExif\Mapper; -use PHPExif\Adapter\Native\Exception\MapperNotRegisteredException; +use PHPExif\Exception\Mapper\MapperNotRegisteredException; /** * Mapper * * @category PHPExif - * @package Adapter + * @package Exif */ trait FieldMapperTrait { @@ -39,6 +39,7 @@ public function registerFieldMappers(array $fieldMappers) /** * Registers given FieldMapper instance + * Allows overwriting an already existing mapper for a given field * * @param FieldMapper $fieldMapper * @@ -49,7 +50,6 @@ public function registerFieldMapper(FieldMapper $fieldMapper) $targetFields = $fieldMapper->getSupportedFields(); foreach ($targetFields as $fieldName) { - // explicitly allow overwriting the FieldMapper for a given field $this->fieldMappers[$fieldName] = $fieldMapper; } } From 6a16731d19e385e20d5983e9b1c8483e43418fdc Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 2 Mar 2016 20:06:13 +0100 Subject: [PATCH 34/51] Unit tests for mapper exceptions Signed-off-by: Tom Van Herreweghe --- .../MapperNotRegisteredExeptionTest.php | 26 +++++++++++++++++ .../Mapper/UnsupportedOutputExeptionTest.php | 28 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 tests/PHPExif/Exception/Mapper/MapperNotRegisteredExeptionTest.php create mode 100644 tests/PHPExif/Exception/Mapper/UnsupportedOutputExeptionTest.php diff --git a/tests/PHPExif/Exception/Mapper/MapperNotRegisteredExeptionTest.php b/tests/PHPExif/Exception/Mapper/MapperNotRegisteredExeptionTest.php new file mode 100644 index 0000000..288fc4f --- /dev/null +++ b/tests/PHPExif/Exception/Mapper/MapperNotRegisteredExeptionTest.php @@ -0,0 +1,26 @@ + + */ +class MapperNotRegisteredExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::forField + */ + public function testForFieldReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + MapperNotRegisteredException::class, + 'forField', + array('foo') + ); + } +} diff --git a/tests/PHPExif/Exception/Mapper/UnsupportedOutputExeptionTest.php b/tests/PHPExif/Exception/Mapper/UnsupportedOutputExeptionTest.php new file mode 100644 index 0000000..f3e0bc1 --- /dev/null +++ b/tests/PHPExif/Exception/Mapper/UnsupportedOutputExeptionTest.php @@ -0,0 +1,28 @@ + + */ +class UnsupportedOutputExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::forOutput + */ + public function testForFieldReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + UnsupportedOutputException::class, + 'forOutput', + array( + (new \stdClass) + ) + ); + } +} From 82635729d417448805028b809e84dcd4060d6718 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 2 Mar 2016 20:11:09 +0100 Subject: [PATCH 35/51] Refactored exception tests for coverage & correct test method names Signed-off-by: Tom Van Herreweghe --- .../Adapter/AdapterAlreadyRegisteredExeptionTest.php | 7 ++++--- .../Exception/Adapter/AdapterNotRegisteredExeptionTest.php | 7 ++++--- .../Collection/ElementAlreadyExistsExeptionTest.php | 5 +++-- .../Exception/Collection/ElementNotExistsExeptionTest.php | 5 +++-- .../Collection/InvalidElementTypeExeptionTest.php | 7 ++++--- tests/PHPExif/Exception/NoExifDataExceptionTest.php | 5 +++-- .../PHPExif/Exception/UnknownAdapterTypeExceptionTest.php | 7 ++++--- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php b/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php index 7919665..f2c9ad6 100644 --- a/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php +++ b/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php @@ -6,15 +6,16 @@ use Tests\PHPExif\Exception\BaseExceptionTest; /** - * @covers \PHPExif\Exception\Adapter\AdapterAlreadyRegisteredException:: + * @coversDefaultClass \PHPExif\Exception\Adapter\AdapterAlreadyRegisteredException + * @covers :: */ class AdapterAlreadyRegisteredExceptionTest extends BaseExceptionTest { /** * @group exception - * @covers \PHPExif\Exception\Adapter\AdapterAlreadyRegisteredException::withName + * @covers ::withName */ - public function testWithKeyReturnsInstance() + public function testWithNameReturnsInstance() { $this->assertNamedConstructorReturnsInstance( AdapterAlreadyRegisteredException::class, diff --git a/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php b/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php index 8715152..eeca030 100644 --- a/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php +++ b/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php @@ -6,15 +6,16 @@ use Tests\PHPExif\Exception\BaseExceptionTest; /** - * @covers \PHPExif\Exception\Adapter\AdapterNotRegisteredException:: + * @coversDefaultClass \PHPExif\Exception\Adapter\AdapterNotRegisteredException + * @covers :: */ class AdapterNotRegisteredExceptionTest extends BaseExceptionTest { /** * @group exception - * @covers \PHPExif\Exception\Adapter\AdapterNotRegisteredException::withName + * @covers ::withName */ - public function testWithKeyReturnsInstance() + public function testWithNameReturnsInstance() { $this->assertNamedConstructorReturnsInstance( AdapterNotRegisteredException::class, diff --git a/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php b/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php index 75408b2..67dcaaf 100644 --- a/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php +++ b/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php @@ -6,13 +6,14 @@ use Tests\PHPExif\Exception\BaseExceptionTest; /** - * @covers \PHPExif\Exception\Collection\ElementAlreadyExistsException:: + * @coversDefaultClass \PHPExif\Exception\Collection\ElementAlreadyExistsException + * @covers :: */ class ElementAlreadyExistsExceptionTest extends BaseExceptionTest { /** * @group exception - * @covers \PHPExif\Exception\Collection\ElementAlreadyExistsException::withKey + * @covers ::withKey */ public function testWithKeyReturnsInstance() { diff --git a/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php b/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php index 83641b7..6d9e3e5 100644 --- a/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php +++ b/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php @@ -6,13 +6,14 @@ use Tests\PHPExif\Exception\BaseExceptionTest; /** - * @covers \PHPExif\Exception\Collection\ElementNotExistsException:: + * @coversDefaultClass \PHPExif\Exception\Collection\ElementNotExistsException + * @covers :: */ class ElementNotExistsExceptionTest extends BaseExceptionTest { /** * @group exception - * @covers \PHPExif\Exception\Collection\ElementNotExistsException::withKey + * @covers ::withKey */ public function testWithKeyReturnsInstance() { diff --git a/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php b/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php index b1adfc0..42f767b 100644 --- a/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php +++ b/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php @@ -6,15 +6,16 @@ use Tests\PHPExif\Exception\BaseExceptionTest; /** - * @covers \PHPExif\Exception\Collection\InvalidElementTypeException:: + * @coversDefaultClass \PHPExif\Exception\Collection\InvalidElementTypeException + * @covers :: */ class InvalidElementTypeExceptionTest extends BaseExceptionTest { /** * @group exception - * @covers \PHPExif\Exception\Collection\InvalidElementTypeException::withExpectedType + * @covers ::withExpectedType */ - public function testWithKeyReturnsInstance() + public function testWithExpectedTypeReturnsInstance() { $this->assertNamedConstructorReturnsInstance( InvalidElementTypeException::class, diff --git a/tests/PHPExif/Exception/NoExifDataExceptionTest.php b/tests/PHPExif/Exception/NoExifDataExceptionTest.php index 326ff21..592238c 100644 --- a/tests/PHPExif/Exception/NoExifDataExceptionTest.php +++ b/tests/PHPExif/Exception/NoExifDataExceptionTest.php @@ -6,13 +6,14 @@ use Tests\PHPExif\Exception\BaseExceptionTest; /** - * @covers \PHPExif\Exception\NoExifDataException:: + * @coversDefaultClass \PHPExif\Exception\NoExifDataException + * @covers :: */ class NoExifDataExceptionTest extends BaseExceptionTest { /** * @group exception - * @covers \PHPExif\Exception\NoExifDataException::fromFile + * @covers ::fromFile */ public function testFromFileReturnsInstance() { diff --git a/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php index dc72581..3487d58 100644 --- a/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php +++ b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php @@ -6,13 +6,14 @@ use Tests\PHPExif\Exception\BaseExceptionTest; /** - * @covers \PHPExif\Exception\UnknownAdapterTypeException:: + * @coversDefaultClass \PHPExif\Exception\UnknownAdapterTypeException + * @covers :: */ class UnknownAdapterTypeExceptionTest extends BaseExceptionTest { /** * @group exception - * @covers \PHPExif\Exception\UnknownAdapterTypeException::forType + * @covers ::forType */ public function testForTypeReturnsInstance() { @@ -25,7 +26,7 @@ public function testForTypeReturnsInstance() /** * @group exception - * @covers \PHPExif\Exception\UnknownAdapterTypeException::noInterface + * @covers ::noInterface */ public function testnoInterfaceReturnsInstance() { From 58e957712a8961da2d3c2192fc4798ede26f96f7 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 2 Mar 2016 21:16:22 +0100 Subject: [PATCH 36/51] Added mockery to dev dependencies Signed-off-by: Tom Van Herreweghe --- composer.json | 3 +- composer.lock | 128 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index e2fdc50..27adf6f 100755 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "phpmd/phpmd": "~2.3.0", "squizlabs/php_codesniffer": "~2.0", "phpunit/phpunit": "~5.2.0", - "satooshi/php-coveralls": "~1.0.0" + "satooshi/php-coveralls": "~1.0.0", + "mockery/mockery": "^0.9.4" }, "suggest": { "lib-exiftool": "Use perl lib exiftool as adapter" diff --git a/composer.lock b/composer.lock index ed18561..c248626 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "74a9535abeda5efbe331027573d7d666", - "content-hash": "22ebb18066da07f1f0a05654f59c8e8a", + "hash": "c7b3e5d58c8d21e2c8ad4a6a19504ee4", + "content-hash": "03314d5c6994f0be1ca1a021bcfc4f84", "packages": [], "packages-dev": [ { @@ -157,6 +157,122 @@ ], "time": "2015-04-29 17:06:53" }, + { + "name": "hamcrest/hamcrest-php", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "b72949ccf2f640e7de66ff7dd92d83f577ce782e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b72949ccf2f640e7de66ff7dd92d83f577ce782e", + "reference": "b72949ccf2f640e7de66ff7dd92d83f577ce782e", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "1.3.3", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ], + "files": [ + "hamcrest/Hamcrest.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "time": "2016-01-19 12:08:55" + }, + { + "name": "mockery/mockery", + "version": "0.9.4", + "source": { + "type": "git", + "url": "https://github.com/padraic/mockery.git", + "reference": "70bba85e4aabc9449626651f48b9018ede04f86b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b", + "reference": "70bba85e4aabc9449626651f48b9018ede04f86b", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "~1.1", + "lib-pcre": ">=7.0", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.9.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", + "homepage": "http://github.com/padraic/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "time": "2015-04-02 19:54:00" + }, { "name": "myclabs/deep-copy", "version": "1.5.0", @@ -1368,7 +1484,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/be0a7044ec8f664c07f117e86633250122af6dbf", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/fd4cddc0663f216c4b9d9f3cd5d52bc08ab3e951", "reference": "be0a7044ec8f664c07f117e86633250122af6dbf", "shasum": "" }, @@ -1498,7 +1614,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/200f109d77649eac204aee729cfc8760f02b3ade", + "url": "https://api.github.com/repos/symfony/console/zipball/dad9b258d9249b5b4bd504a5ee0483c7a5906660", "reference": "200f109d77649eac204aee729cfc8760f02b3ade", "shasum": "" }, @@ -1558,7 +1674,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c6c4ab94df002d6f3648b488ca96727c4b9b2df8", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9d54eec130500072f3a1939ca4606de1428469c3", "reference": "c6c4ab94df002d6f3648b488ca96727c4b9b2df8", "shasum": "" }, @@ -1834,7 +1950,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/939b8e10c4e0e1135144fb09e12a3d32ff129e4a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ab0314f7544d600ea7917f02cdad774358b81113", "reference": "939b8e10c4e0e1135144fb09e12a3d32ff129e4a", "shasum": "" }, From f8c99ecba507ce16ca696299cc5ddbaff2754214 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 10 Mar 2016 16:24:41 +0100 Subject: [PATCH 37/51] Wrote tests for Native mapper + small refactor Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/Mapper.php | 31 ++- tests/PHPExif/Adapter/Native/MapperTest.php | 268 ++++++++++++++++++++ 2 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 tests/PHPExif/Adapter/Native/MapperTest.php diff --git a/src/PHPExif/Adapter/Native/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php index 401136e..84eafa8 100644 --- a/src/PHPExif/Adapter/Native/Mapper.php +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -47,12 +47,37 @@ public function map(array $data) */ public function mapArray(array $input, $output) { - $exif = $output->getExif(); - $exifMapper = $this->getFieldMapper(self::FIELD_EXIF); - $exifMapper->mapArray($input, $exif); + $this->mapExif($input, $output); + $this->mapIptc($input, $output); + } + /** + * Maps the IPTC data + * + * @param array $input + * @param object $output + * + * @return void + */ + private function mapIptc($input, $output) + { $iptc = $output->getIptc(); $iptcMapper = $this->getFieldMapper(self::FIELD_IPTC); $iptcMapper->mapArray($input, $iptc); } + + /** + * Maps the EXIF data + * + * @param array $input + * @param object $output + * + * @return void + */ + private function mapExif($input, $output) + { + $exif = $output->getExif(); + $exifMapper = $this->getFieldMapper(self::FIELD_EXIF); + $exifMapper->mapArray($input, $exif); + } } diff --git a/tests/PHPExif/Adapter/Native/MapperTest.php b/tests/PHPExif/Adapter/Native/MapperTest.php new file mode 100644 index 0000000..8848649 --- /dev/null +++ b/tests/PHPExif/Adapter/Native/MapperTest.php @@ -0,0 +1,268 @@ + + */ +class MapperTest extends \PHPUnit_Framework_TestCase +{ + /** + * @group mapper + * + * @return void + */ + public function testIfClassImplementsInterface() + { + $mock = m::mock(Mapper::class); + $this->assertInstanceOf( + ArrayMapper::class, + $mock + ); + } + + /** + * @covers ::registerFieldMappers + * @group mapper + * + * @return void + */ + public function testRegisterFieldMappersCallsInternalMethod() + { + $fieldMappers = array( + m::mock(FieldMapper::class), + m::mock(FieldMapper::class), + m::mock(FieldMapper::class), + m::mock(FieldMapper::class), + ); + + $ctr = 0; + $mock = m::mock(Mapper::class . '[registerFieldMapper]'); + $mock->shouldReceive('registerFieldMapper') + ->with( + m::on( + function ($arg) use ($fieldMappers, &$ctr) { + $result = false; + if ($arg === $fieldMappers[$ctr]) { + $result = true; + } + + $ctr++; + + return $result; + } + ) + ) + ->times(count($fieldMappers)) + ->andReturn(null); + + $mock->registerFieldMappers($fieldMappers); + } + + /** + * @covers ::registerFieldMapper + * @group mapper + * + * @return void + */ + public function testRegisterFieldMapperAddsToList() + { + $reflField = new \ReflectionProperty( + Mapper::class, + 'fieldMappers' + ); + $reflField->setAccessible(true); + + $mock = m::mock(Mapper::class)->makePartial(); + + $this->assertCount( + 0, + $reflField->getValue($mock) + ); + + $field = 'foo'; + $fieldMapper = m::mock(FieldMapper::class . '[getSupportedFields]'); + $fieldMapper->shouldReceive('getSupportedFields') + ->once() + ->andReturn(array($field)); + + $mock->registerFieldMapper($fieldMapper); + + $this->assertCount( + 1, + $reflField->getValue($mock) + ); + } + + /** + * @covers ::registerFieldMapper + * @group mapper + * + * @return void + */ + public function testRegisterFieldMapperAllowsOverwritingExisting() + { + $mock = m::mock(Mapper::class)->makePartial(); + + $field = 'foo'; + $fieldMapper = m::mock(FieldMapper::class . '[getSupportedFields]'); + $fieldMapper->shouldReceive('getSupportedFields') + ->once() + ->andReturn(array($field)); + + $fieldMapper2 = clone $fieldMapper; + + $mock->registerFieldMapper($fieldMapper); + $mock->registerFieldMapper($fieldMapper2); + + $result = $mock->getFieldMapper($field); + $this->assertSame($fieldMapper2, $result); + } + + /** + * @covers ::getFieldMapper + * @group mapper + * + * @return void + */ + public function testGetFieldMapperReturnsFromList() + { + $field = 'foo'; + $mock = m::mock(Mapper::class)->makePartial(); + $fieldMapper = m::mock(FieldMapper::class); + $reflField = new \ReflectionProperty( + Mapper::class, + 'fieldMappers' + ); + $reflField->setAccessible(true); + $reflField->setValue($mock, array($field => $fieldMapper,)); + + $actual = $mock->getFieldMapper($field); + + $this->assertSame( + $fieldMapper, + $actual + ); + } + + /** + * @covers ::getFieldMapper + * @group mapper + * @expectedException \PHPExif\Exception\Mapper\MapperNotRegisteredException + * + * @return void + */ + public function testGetFieldMapperThrowsExceptionForUnknownMapper() + { + $field = 'foo'; + $mock = m::mock(Mapper::class)->makePartial(); + $mock->getFieldMapper($field); + } + + /** + * @covers ::mapperRegisteredForField + * @group mapper + * + * @return void + */ + public function testMapperRegisteredForFieldCorrectlyDeterminesIfMapperIsRegistered() + { + $field = 'foo'; + $mock = m::mock(Mapper::class)->makePartial(); + $fieldMapper = m::mock(FieldMapper::class . '[getSupportedFields]'); + $fieldMapper->shouldReceive('getSupportedFields') + ->once() + ->andReturn(array($field)); + $reflField = new \ReflectionProperty( + Mapper::class, + 'fieldMappers' + ); + $reflField->setAccessible(true); + $reflField->setValue($mock, array($field => $fieldMapper,)); + + $this->assertTrue( + $mock->mapperRegisteredForField($field) + ); + $this->assertFalse( + $mock->mapperRegisteredForField('bar') + ); + } + + /** + * @covers ::map + * @group mapper + * + * @return void + */ + public function testMapForwardsCall() + { + $data = array(); + + $mock = m::mock(Mapper::class . '[mapArray]')->makePartial(); + $mock->shouldReceive('mapArray') + ->once() + ->with( + $data, + m::type(Metadata::class) + ) + ->andReturnNull(); + + $actual = $mock->map($data); + + $this->assertInstanceOf( + Metadata::class, + $actual + ); + } + + /** + * @covers ::mapArray + * @group mapper + * + * @return void + */ + public function testMapArrayForwardsCall() + { + $exif = new Exif(array()); + $iptc = new Iptc(array()); + + $input = array(); + $metadata = new MetaData; + $output = m::mock($metadata); + $output->shouldReceive('getExif') + ->once() + ->andReturn($exif); + $output->shouldReceive('getIptc') + ->once() + ->andReturn($iptc); + + $mapper = new Mapper; + + foreach (array(Mapper::FIELD_EXIF, MAPPER::FIELD_IPTC) as $field) { + $fieldMapper = m::mock(FieldMapper::class . '[getSupportedFields,mapArray]'); + $fieldMapper->shouldReceive('getSupportedFields') + ->once() + ->andReturn(array($field)); + $fieldMapper->shouldReceive('mapArray') + ->once() + ->with( + $input, + ($field === Mapper::FIELD_EXIF) ? $exif : $iptc + ) + ->andReturnNull(); + + $mapper->registerFieldMapper($fieldMapper); + } + + $mapper->mapArray($input, $output); + } +} From a10d98a27ea2f3bdb8fc65df968db83cef90ab4f Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 10 Mar 2016 16:32:52 +0100 Subject: [PATCH 38/51] Changed branch name in README links to TravisCI Signed-off-by: Tom Van Herreweghe --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8b2396..aac21d4 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# [PHPExif v1.0.0-prealpha](http://github.com/Miljar/php-exif) [![Build Status](https://travis-ci.org/Miljar/php-exif.png?branch=feature/rewrite)](https://travis-ci.org/Miljar/php-exif) [![Coverage Status](https://coveralls.io/repos/Miljar/php-exif/badge.svg?branch=feature/rewrite)](https://coveralls.io/r/Miljar/php-exif?branch=feature/rewrite) [![Code Climate](https://codeclimate.com/github/Miljar/php-exif/badges/gpa.svg)](https://codeclimate.com/github/Miljar/php-exif) +# [PHPExif v1.0.0-prealpha](http://github.com/Miljar/php-exif) [![Build Status](https://travis-ci.org/Miljar/php-exif.png?branch=develop)](https://travis-ci.org/Miljar/php-exif) [![Coverage Status](https://coveralls.io/repos/Miljar/php-exif/badge.svg?branch=develop)](https://coveralls.io/r/Miljar/php-exif?branch=develop) [![Code Climate](https://codeclimate.com/github/Miljar/php-exif/badges/gpa.svg)](https://codeclimate.com/github/Miljar/php-exif) PHPExif is a library which gives you easy access to the EXIF meta-data of an image. From a5f8b13f990f5a99caad54259f00392ffd2bfd7b Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 10 Mar 2016 16:44:27 +0100 Subject: [PATCH 39/51] Fixed casing issue with MetaData Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/Mapper.php | 2 +- tests/PHPExif/Adapter/Native/MapperTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PHPExif/Adapter/Native/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php index 84eafa8..4e09baf 100644 --- a/src/PHPExif/Adapter/Native/Mapper.php +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -13,7 +13,7 @@ namespace PHPExif\Adapter\Native; use PHPExif\Adapter\MapperInterface; -use PHPExif\Data\MetaData; +use PHPExif\Data\Metadata; use PHPExif\Mapper\ArrayMapper; use PHPExif\Mapper\FieldMapperTrait; diff --git a/tests/PHPExif/Adapter/Native/MapperTest.php b/tests/PHPExif/Adapter/Native/MapperTest.php index 8848649..9383128 100644 --- a/tests/PHPExif/Adapter/Native/MapperTest.php +++ b/tests/PHPExif/Adapter/Native/MapperTest.php @@ -6,7 +6,7 @@ use PHPExif\Adapter\Native\Mapper; use PHPExif\Data\Exif; use PHPExif\Data\Iptc; -use PHPExif\Data\MetaData; +use PHPExif\Data\Metadata; use PHPExif\Mapper\ArrayMapper; use PHPExif\Mapper\FieldMapper; @@ -236,7 +236,7 @@ public function testMapArrayForwardsCall() $iptc = new Iptc(array()); $input = array(); - $metadata = new MetaData; + $metadata = new Metadata; $output = m::mock($metadata); $output->shouldReceive('getExif') ->once() From c587e82c4d05b3c38cde19a015204142e5f467b1 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 21 Mar 2016 12:28:18 +0100 Subject: [PATCH 40/51] Constructor test for AbstractCollection Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/AbstractCollectionTest.php | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/PHPExif/AbstractCollectionTest.php diff --git a/tests/PHPExif/AbstractCollectionTest.php b/tests/PHPExif/AbstractCollectionTest.php new file mode 100644 index 0000000..7f4e9bf --- /dev/null +++ b/tests/PHPExif/AbstractCollectionTest.php @@ -0,0 +1,81 @@ + + */ +class AbstractCollectionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers ::__construct + * @group collection + * + * @return void + */ + public function testConstructorAddsElementsFromParameter() + { + $input = array( + 'foo' => 'bar', + 'baz' => 'quux', + ); + $ctr = array( + 'key' => 0, + 'value' => 0, + ); + + $checker = function ($type) use ($input, &$ctr) { + return function ($arg) use ($input, $type, &$ctr) { + $result = false; + + $data = null; + if ($type === 'key') { + $data = array_keys($input); + } else { + $data = array_values($input); + } + + if ($arg === $data[$ctr[$type]]) { + $result = true; + } + + $ctr[$type]++; + + return $result; + }; + }; + + $mock = m::mock( + AbstractCollection::class + )->shouldDeferMissing(); + $mock->shouldReceive('add') + ->with( + m::on( + $checker('key') + ), + m::on( + $checker('value') + ) + ) + ->andReturnNull(); + + $mock->__construct($input); + + $this->assertEquals( + count($input), + $ctr['key'] + ); + $this->assertEquals( + count($input), + $ctr['value'] + ); + } +} From 78c24046167a48fdae84d1159e3a6d14d8dde06b Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 21 Mar 2016 20:13:59 +0100 Subject: [PATCH 41/51] Bugfixes all around Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/Mapper.php | 12 +++-- .../Mapper/Exif/ApertureFieldMapper.php | 2 +- .../Adapter/Native/Mapper/ExifMapper.php | 45 +++++++++++++++++-- .../Adapter/Native/Mapper/IptcMapper.php | 45 +++++++++++++++++-- .../Adapter/Native/NativeAdapterConfig.php | 1 + src/PHPExif/Adapter/Native/ReaderConfig.php | 2 +- src/PHPExif/Data/Exif.php | 14 +++++- src/PHPExif/Data/ExifInterface.php | 13 +++++- src/PHPExif/Data/Iptc.php | 4 +- src/PHPExif/Mapper/ArrayMapper.php | 2 +- src/PHPExif/Mapper/FieldMapper.php | 2 +- 11 files changed, 120 insertions(+), 22 deletions(-) diff --git a/src/PHPExif/Adapter/Native/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php index 4e09baf..d9ccd31 100644 --- a/src/PHPExif/Adapter/Native/Mapper.php +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -45,7 +45,7 @@ public function map(array $data) /** * {@inheritDoc} */ - public function mapArray(array $input, $output) + public function mapArray(array $input, &$output) { $this->mapExif($input, $output); $this->mapIptc($input, $output); @@ -59,11 +59,10 @@ public function mapArray(array $input, $output) * * @return void */ - private function mapIptc($input, $output) + private function mapIptc($input, &$output) { - $iptc = $output->getIptc(); $iptcMapper = $this->getFieldMapper(self::FIELD_IPTC); - $iptcMapper->mapArray($input, $iptc); + $iptcMapper->mapField(self::FIELD_IPTC, $input, $output); } /** @@ -74,10 +73,9 @@ private function mapIptc($input, $output) * * @return void */ - private function mapExif($input, $output) + private function mapExif($input, &$output) { - $exif = $output->getExif(); $exifMapper = $this->getFieldMapper(self::FIELD_EXIF); - $exifMapper->mapArray($input, $exif); + $exifMapper->mapField(self::FIELD_EXIF, $input, $output); } } diff --git a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php index c51411b..ff435c5 100644 --- a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php @@ -42,6 +42,6 @@ public function mapField($field, array $input, &$output) { $this->guardInvalidArguments($field, $input, $output); - $output = $output->withAperture((float) $input['ApertureFNumber']); + $output = $output->withAperture($input['COMPUTED']['ApertureFNumber']); } } diff --git a/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php b/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php index 9e5f03b..b717b79 100644 --- a/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php @@ -12,9 +12,15 @@ namespace PHPExif\Adapter\Native\Mapper; +use PHPExif\Adapter\Native\Exception\UnsupportedFieldException; +use PHPExif\Adapter\Native\Mapper; +use PHPExif\Data\Exif; use PHPExif\Data\ExifInterface; +use PHPExif\Data\MetadataInterface; +use PHPExif\Exception\Mapper\MapperNotRegisteredException; use PHPExif\Exception\Mapper\UnsupportedOutputException; use PHPExif\Mapper\ArrayMapper; +use PHPExif\Mapper\FieldMapper; use PHPExif\Mapper\FieldMapperTrait; /** @@ -23,14 +29,24 @@ * @category PHPExif * @package Adapter */ -class ExifMapper implements ArrayMapper +class ExifMapper implements ArrayMapper, FieldMapper { use FieldMapperTrait; /** * {@inheritDoc} */ - public function mapArray(array $input, $output) + public function getSupportedFields() + { + return array( + Mapper::FIELD_EXIF, + ); + } + + /** + * {@inheritDoc} + */ + public function mapArray(array $input, &$output) { if (!($output instanceof ExifInterface)) { throw UnsupportedOutputException::forOutput($output); @@ -40,7 +56,12 @@ public function mapArray(array $input, $output) $fields = array_keys($data); foreach ($fields as $name) { - $fieldMapper = $this->getFieldMapper($name); + try { + $fieldMapper = $this->getFieldMapper($name); + } catch (MapperNotRegisteredException $e) { + // silently ignore missing FieldMapper + continue; + } $fieldMapper->mapField( $name, @@ -49,4 +70,22 @@ public function mapArray(array $input, $output) ); } } + + /** + * {@inheritDoc} + */ + public function mapField($field, array $input, &$output) + { + if (!in_array($field, $this->getSupportedFields())) { + throw UnsupportedFieldException::forField($field); + } + + if (!($output instanceof MetadataInterface)) { + throw UnsupportedOutputException::forOutput($output); + } + + $exif = $output->getExif(); + $this->mapArray($input, $exif); + $output = $output->withExif($exif); + } } diff --git a/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php b/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php index 80ae62a..5ef495d 100644 --- a/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php @@ -12,9 +12,15 @@ namespace PHPExif\Adapter\Native\Mapper; +use PHPExif\Adapter\Native\Exception\UnsupportedFieldException; +use PHPExif\Adapter\Native\Mapper; +use PHPExif\Data\Iptc; use PHPExif\Data\IptcInterface; +use PHPExif\Data\MetadataInterface; +use PHPExif\Exception\Mapper\MapperNotRegisteredException; use PHPExif\Exception\Mapper\UnsupportedOutputException; use PHPExif\Mapper\ArrayMapper; +use PHPExif\Mapper\FieldMapper; use PHPExif\Mapper\FieldMapperTrait; /** @@ -23,14 +29,24 @@ * @category PHPExif * @package Adapter */ -class IptcMapper implements ArrayMapper +class IptcMapper implements ArrayMapper, FieldMapper { use FieldMapperTrait; /** * {@inheritDoc} */ - public function mapArray(array $input, $output) + public function getSupportedFields() + { + return array( + Mapper::FIELD_IPTC, + ); + } + + /** + * {@inheritDoc} + */ + public function mapArray(array $input, &$output) { if (!($output instanceof IptcInterface)) { throw UnsupportedOutputException::forOutput($output); @@ -40,7 +56,12 @@ public function mapArray(array $input, $output) $fields = array_keys($data); foreach ($fields as $name) { - $fieldMapper = $this->getFieldMapper($name); + try { + $fieldMapper = $this->getFieldMapper($name); + } catch (MapperNotRegisteredException $e) { + // silently ignore missing FieldMapper + continue; + } $fieldMapper->mapField( $name, @@ -49,4 +70,22 @@ public function mapArray(array $input, $output) ); } } + + /** + * {@inheritDoc} + */ + public function mapField($field, array $input, &$output) + { + if (!in_array($field, $this->getSupportedFields())) { + throw UnsupportedFieldException::forField($field); + } + + if (!($output instanceof MetadataInterface)) { + throw UnsupportedOutputException::forOutput($output); + } + + $iptc = $output->getIptc(); + $this->mapArray($input, $iptc); + $output = $output->withIptc($iptc); + } } diff --git a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php index 357a476..a3fbf27 100644 --- a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php +++ b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php @@ -13,6 +13,7 @@ use PHPExif\Adapter\AdapterConfig; use PHPExif\Adapter\HasMapper; +use PHPExif\Adapter\MapperAccessorTrait; use PHPExif\Adapter\Native\Reader; use PHPExif\Adapter\Native\ReaderConfig; diff --git a/src/PHPExif/Adapter/Native/ReaderConfig.php b/src/PHPExif/Adapter/Native/ReaderConfig.php index 1ec9d78..e5b05c3 100644 --- a/src/PHPExif/Adapter/Native/ReaderConfig.php +++ b/src/PHPExif/Adapter/Native/ReaderConfig.php @@ -10,7 +10,7 @@ * @package Adapter */ -namespace PHPExif\Adapter\Native\Reader; +namespace PHPExif\Adapter\Native; /** * ReaderConfig class diff --git a/src/PHPExif/Data/Exif.php b/src/PHPExif/Data/Exif.php index 5db42a2..c64d763 100644 --- a/src/PHPExif/Data/Exif.php +++ b/src/PHPExif/Data/Exif.php @@ -22,7 +22,7 @@ final class Exif implements ExifInterface { /** - * @var float + * @var string */ private $aperture; @@ -44,4 +44,16 @@ public function withAperture($aperture) return $new; } + + /** + * {@inheritDoc} + */ + public function toArray($withEmpty = true) + { + $data = get_class_vars( + self::class + ); + + return $data; + } } diff --git a/src/PHPExif/Data/ExifInterface.php b/src/PHPExif/Data/ExifInterface.php index a687c6a..c89d6a3 100644 --- a/src/PHPExif/Data/ExifInterface.php +++ b/src/PHPExif/Data/ExifInterface.php @@ -51,16 +51,25 @@ interface ExifInterface /** * Accessor for the aperture * - * @return float + * @return string */ public function getAperture(); /** * Returns new instance with updated aperture * - * @param float $aperture + * @param string $aperture * * @return ExifInterface */ public function withAperture($aperture); + + /** + * Array represenation of current instance + * + * @param boolean $withEmpty + * + * @return array + */ + public function toArray($withEmpty = true); } diff --git a/src/PHPExif/Data/Iptc.php b/src/PHPExif/Data/Iptc.php index 4e52119..0df13fd 100644 --- a/src/PHPExif/Data/Iptc.php +++ b/src/PHPExif/Data/Iptc.php @@ -83,7 +83,7 @@ final class Iptc implements IptcInterface public function __construct(array $data) { foreach ($data as $key => $value) { - if (!array_key_exists($key, $this->iptcMapping)) { + if (!array_key_exists($key, self::$iptcMapping)) { continue; } @@ -97,7 +97,7 @@ public function __construct(array $data) public function toArray($withEmpty = true) { $data = array(); - $keys = array_keys($this->iptcMapping); + $keys = array_keys(self::$iptcMapping); foreach ($keys as $prop) { $accessor = 'get' . ucfirst($prop); $value = $this->$accessor(); diff --git a/src/PHPExif/Mapper/ArrayMapper.php b/src/PHPExif/Mapper/ArrayMapper.php index 67e341a..cf6d6d0 100644 --- a/src/PHPExif/Mapper/ArrayMapper.php +++ b/src/PHPExif/Mapper/ArrayMapper.php @@ -60,5 +60,5 @@ public function getFieldMapper($field); * * @return void */ - public function mapArray(array $input, $output); + public function mapArray(array $input, &$output); } diff --git a/src/PHPExif/Mapper/FieldMapper.php b/src/PHPExif/Mapper/FieldMapper.php index f8ec2af..3f2e6aa 100644 --- a/src/PHPExif/Mapper/FieldMapper.php +++ b/src/PHPExif/Mapper/FieldMapper.php @@ -41,5 +41,5 @@ public function getSupportedFields(); * * @return void */ - public function mapField($field, array $input, $output); + public function mapField($field, array $input, &$output); } From d7248a566d02d5d4a53e66d32d6372ee817cf750 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 21 Mar 2016 20:20:12 +0100 Subject: [PATCH 42/51] Fixed MapperTest Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Adapter/Native/MapperTest.php | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/PHPExif/Adapter/Native/MapperTest.php b/tests/PHPExif/Adapter/Native/MapperTest.php index 9383128..72c6e83 100644 --- a/tests/PHPExif/Adapter/Native/MapperTest.php +++ b/tests/PHPExif/Adapter/Native/MapperTest.php @@ -1,6 +1,6 @@ shouldReceive('getExif') - ->once() - ->andReturn($exif); - $output->shouldReceive('getIptc') - ->once() - ->andReturn($iptc); + $output = new Metadata; $mapper = new Mapper; foreach (array(Mapper::FIELD_EXIF, MAPPER::FIELD_IPTC) as $field) { - $fieldMapper = m::mock(FieldMapper::class . '[getSupportedFields,mapArray]'); + $fieldMapper = m::mock(FieldMapper::class . '[getSupportedFields,mapField]'); $fieldMapper->shouldReceive('getSupportedFields') ->once() ->andReturn(array($field)); - $fieldMapper->shouldReceive('mapArray') + $fieldMapper->shouldReceive('mapField') ->once() ->with( + $field, $input, - ($field === Mapper::FIELD_EXIF) ? $exif : $iptc + m::type(Metadata::class) ) ->andReturnNull(); From 895d1dbe3fc8207f6dc282944ca79aa6c0696efb Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 21 Mar 2016 21:10:05 +0100 Subject: [PATCH 43/51] Created and used Aperture value object Signed-off-by: Tom Van Herreweghe --- .../Mapper/Exif/ApertureFieldMapper.php | 7 +- src/PHPExif/Data/Exif.php | 4 +- src/PHPExif/Data/Exif/Aperture.php | 88 +++++++++++++++++++ src/PHPExif/Data/ExifInterface.php | 8 +- 4 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 src/PHPExif/Data/Exif/Aperture.php diff --git a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php index ff435c5..75c0c03 100644 --- a/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php +++ b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php @@ -13,6 +13,7 @@ namespace PHPExif\Adapter\Native\Mapper\Exif; use PHPExif\Data\ExifInterface; +use PHPExif\Data\Exif\Aperture; use PHPExif\Mapper\FieldMapper; /** @@ -42,6 +43,10 @@ public function mapField($field, array $input, &$output) { $this->guardInvalidArguments($field, $input, $output); - $output = $output->withAperture($input['COMPUTED']['ApertureFNumber']); + $aperture = Aperture::fromFocalLength( + $input['COMPUTED']['ApertureFNumber'] + ); + + $output = $output->withAperture($aperture); } } diff --git a/src/PHPExif/Data/Exif.php b/src/PHPExif/Data/Exif.php index c64d763..d4b1040 100644 --- a/src/PHPExif/Data/Exif.php +++ b/src/PHPExif/Data/Exif.php @@ -11,6 +11,8 @@ namespace PHPExif\Data; +use PHPExif\Data\Exif\Aperture; + /** * Exif class * @@ -37,7 +39,7 @@ public function getAperture() /** * {@inheritDoc} */ - public function withAperture($aperture) + public function withAperture(Aperture $aperture) { $new = clone $this; $new->aperture = $aperture; diff --git a/src/PHPExif/Data/Exif/Aperture.php b/src/PHPExif/Data/Exif/Aperture.php new file mode 100644 index 0000000..8976cc1 --- /dev/null +++ b/src/PHPExif/Data/Exif/Aperture.php @@ -0,0 +1,88 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data\Exif; + +/*i + * Aperture class + * + * A value object to describe the Aperture f-number + * + * @category PHPExif + * @package Exif + */ +final class Aperture implements \JsonSerializable +{ + /** + * The f-number + * + * @see https://en.wikipedia.org/wiki/F-number + * + * @var float + */ + private $fNumber; + + /** + * @param float $fNumber + * + * @throws \InvalidArgumentException If given f-number is not a float + */ + public function __construct($fNumber) + { + if (filter_var($fNumber, FILTER_VALIDATE_FLOAT) === false) { + throw new \InvalidArgumentException('fNumber must be a float'); + } + + $this->fNumber = $fNumber; + } + + /** + * Creates new instance from given Focal Length format + * + * @param string $focalLength + * + * @throws \InvalidArgumentException If focalLength is not a string + */ + public static function fromFocalLength($focalLength) + { + if (!is_string($focalLength)) { + throw new \InvalidArgumentException('focalLength must be a string'); + } + + if (!preg_match('#f/([0-9]*\.[0-9]?)#', $focalLength, $matches)) { + throw new \RuntimeException('Given focalLength is not in a valid format. Need: "f/"'); + } + + $fNumber = (float) $matches[1]; + + return new static($fNumber); + } + + /** + * {@inheritdoc} + * + * @return string + */ + public function jsonSerialize() + { + return (string) $this; + } + + /** + * Returns string representation + * + * @return string + */ + public function __toString() + { + return 'f/' . $this->fNumber; + } +} diff --git a/src/PHPExif/Data/ExifInterface.php b/src/PHPExif/Data/ExifInterface.php index c89d6a3..b78a71e 100644 --- a/src/PHPExif/Data/ExifInterface.php +++ b/src/PHPExif/Data/ExifInterface.php @@ -11,6 +11,8 @@ namespace PHPExif\Data; +use PHPExif\Data\Exif\Aperture; + /** * ExifInterface * @@ -51,18 +53,18 @@ interface ExifInterface /** * Accessor for the aperture * - * @return string + * @return Aperture */ public function getAperture(); /** * Returns new instance with updated aperture * - * @param string $aperture + * @param Aperture $aperture * * @return ExifInterface */ - public function withAperture($aperture); + public function withAperture(Aperture $aperture); /** * Array represenation of current instance From 1f3cd43c4acac4059159bbdcd10264d38bd05c0c Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 21 Mar 2016 21:14:21 +0100 Subject: [PATCH 44/51] Made sure string representation of f-number is always with decimal Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/Exif/Aperture.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/PHPExif/Data/Exif/Aperture.php b/src/PHPExif/Data/Exif/Aperture.php index 8976cc1..0393357 100644 --- a/src/PHPExif/Data/Exif/Aperture.php +++ b/src/PHPExif/Data/Exif/Aperture.php @@ -83,6 +83,9 @@ public function jsonSerialize() */ public function __toString() { - return 'f/' . $this->fNumber; + return sprintf( + 'f/%1.1f', + $this->fNumber + ); } } From ae0269d24aff7d339c30c2c54545c0cfbbf60f42 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Tue, 29 Mar 2016 13:05:10 +0200 Subject: [PATCH 45/51] Unit test for Aperture Value Object Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/Exif/Aperture.php | 2 +- tests/PHPExif/Data/Exif/ApertureTest.php | 164 +++++++++++++++++++++++ 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 tests/PHPExif/Data/Exif/ApertureTest.php diff --git a/src/PHPExif/Data/Exif/Aperture.php b/src/PHPExif/Data/Exif/Aperture.php index 0393357..778dbfd 100644 --- a/src/PHPExif/Data/Exif/Aperture.php +++ b/src/PHPExif/Data/Exif/Aperture.php @@ -41,7 +41,7 @@ public function __construct($fNumber) throw new \InvalidArgumentException('fNumber must be a float'); } - $this->fNumber = $fNumber; + $this->fNumber = (float) $fNumber; } /** diff --git a/tests/PHPExif/Data/Exif/ApertureTest.php b/tests/PHPExif/Data/Exif/ApertureTest.php new file mode 100644 index 0000000..55869fc --- /dev/null +++ b/tests/PHPExif/Data/Exif/ApertureTest.php @@ -0,0 +1,164 @@ + + */ +class ApertureTest extends \PHPUnit_Framework_TestCase +{ + /** + * @group data + * @group exif + * + * @covers ::fromFocalLength + * + * @dataProvider fromFocalLengthProvider + * + * @param mixed $focalLength + * @param string $exceptionClass + * @param string $message + * + * @return void + */ + public function testFromFocalLengthThrowsExceptionsForInvalidArgument( + $focalLength, + $exceptionClass, + $message + ) { + try { + Aperture::fromFocalLength($focalLength); + $this->fail('Test should not pass'); + } catch (\Exception $e) { + $this->assertEquals( + $exceptionClass, + get_class($e) + ); + + $this->assertEquals( + $message, + $e->getMessage() + ); + } + } + + /** + * fromFocalLengthProvider + * + * @return array + */ + public function fromFocalLengthProvider() + { + return [ + [ + 8.0, + \InvalidArgumentException::class, + 'focalLength must be a string', + ], + [ + 'f/8', + \RuntimeException::class, + 'Given focalLength is not in a valid format. Need: "f/"', + ], + ]; + } + + /** + * @group data + * @group exif + * + * @return void + */ + public function testFromFocalLengthReturnsInstance() + { + $actual = Aperture::fromFocalLength('f/8.0'); + $this->assertInstanceOf( + Aperture::class, + $actual + ); + } + + /** + * @group data + * @group exif + * + * @covers ::__construct + * + * @dataProvider constructorArgumentsProvider + * + * @return void + */ + public function testConstructorValidatesFloat($value) + { + try { + new Aperture($value); + $this->fail(); + } catch (\InvalidArgumentException $e) { + } + } + + /** + * constructorArgumentsProvider + * + * @return array + */ + public function constructorArgumentsProvider() + { + return [ + ['foo'], + [false], + ]; + } + + /** + * @group data + * @group exif + * + * @covers ::jsonSerialize + * + * @return void + */ + public function testJsonSerializeReturnsString() + { + $instance = new Aperture(8.0); + $actual = $instance->jsonSerialize(); + + $this->assertInternalType( + 'string', + $actual + ); + + $this->assertEquals( + '"f\/8.0"', + json_encode($instance) + ); + } + + /** + * @group data + * @group exif + * + * @covers ::__toString + * + * @return void + */ + public function testToStringReturnsString() + { + $instance = new Aperture(8.0); + $actual = (string) $instance; + + $this->assertInternalType( + 'string', + $actual + ); + + $this->assertEquals( + 'f/8.0', + $actual + ); + } +} From 6bf032770a0122e9882a81ec20cd52ce6009db46 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Tue, 29 Mar 2016 19:37:10 +0200 Subject: [PATCH 46/51] Allow empty IPTC constructor Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/Iptc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PHPExif/Data/Iptc.php b/src/PHPExif/Data/Iptc.php index 0df13fd..147759b 100644 --- a/src/PHPExif/Data/Iptc.php +++ b/src/PHPExif/Data/Iptc.php @@ -80,7 +80,7 @@ final class Iptc implements IptcInterface /** * @param array $data */ - public function __construct(array $data) + public function __construct(array $data = array()) { foreach ($data as $key => $value) { if (!array_key_exists($key, self::$iptcMapping)) { From a249f08193b85cf5a514dcdd206f5e7494b5beb2 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Tue, 29 Mar 2016 19:37:38 +0200 Subject: [PATCH 47/51] Metadata constructor expects Exif & Iptc objects Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/Metadata.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/PHPExif/Data/Metadata.php b/src/PHPExif/Data/Metadata.php index e4cc10b..5f8f9b8 100644 --- a/src/PHPExif/Data/Metadata.php +++ b/src/PHPExif/Data/Metadata.php @@ -31,6 +31,18 @@ final class Metadata implements MetadataInterface */ private $iptc; + /** + * Constructor + * + * @param ExifInterface $exif + * @param IptcInterface $iptc + */ + public function __construct(ExifInterface $exif, IptcInterface $iptc) + { + $this->exif = $exif; + $this->iptc = $iptc; + } + /** * {@inheritDoc} */ From 93ad877e4f17023862a0211accebfe704ba90814 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Tue, 29 Mar 2016 19:37:57 +0200 Subject: [PATCH 48/51] Fixes to Mapper & test Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Adapter/Native/Mapper.php | 7 ++++++- tests/PHPExif/Adapter/Native/MapperTest.php | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/PHPExif/Adapter/Native/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php index d9ccd31..06d6c5e 100644 --- a/src/PHPExif/Adapter/Native/Mapper.php +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -13,6 +13,8 @@ namespace PHPExif\Adapter\Native; use PHPExif\Adapter\MapperInterface; +use PHPExif\Data\Exif; +use PHPExif\Data\Iptc; use PHPExif\Data\Metadata; use PHPExif\Mapper\ArrayMapper; use PHPExif\Mapper\FieldMapperTrait; @@ -35,7 +37,10 @@ class Mapper implements MapperInterface, ArrayMapper */ public function map(array $data) { - $output = new Metadata; + $output = new Metadata( + new Exif, + new Iptc + ); $this->mapArray($data, $output); diff --git a/tests/PHPExif/Adapter/Native/MapperTest.php b/tests/PHPExif/Adapter/Native/MapperTest.php index 72c6e83..d3fdf66 100644 --- a/tests/PHPExif/Adapter/Native/MapperTest.php +++ b/tests/PHPExif/Adapter/Native/MapperTest.php @@ -233,7 +233,10 @@ public function testMapForwardsCall() public function testMapArrayForwardsCall() { $input = array(); - $output = new Metadata; + $output = new Metadata( + new Exif, + new Iptc + ); $mapper = new Mapper; From fc5ab6795a4e69c81f37b59142f9841cd0708815 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Tue, 29 Mar 2016 19:53:46 +0200 Subject: [PATCH 49/51] Unit tests for Metadata class Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/Metadata.php | 8 -- tests/PHPExif/Data/MetadataTest.php | 134 ++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 tests/PHPExif/Data/MetadataTest.php diff --git a/src/PHPExif/Data/Metadata.php b/src/PHPExif/Data/Metadata.php index 5f8f9b8..ce05129 100644 --- a/src/PHPExif/Data/Metadata.php +++ b/src/PHPExif/Data/Metadata.php @@ -70,10 +70,6 @@ public function withIptc(IptcInterface $iptc) */ public function getExif() { - if (null === $this->exif) { - $this->exif = new Exif; - } - return $this->exif; } @@ -82,10 +78,6 @@ public function getExif() */ public function getIptc() { - if (null === $this->iptc) { - $this->iptc = new Iptc(array()); - } - return $this->iptc; } } diff --git a/tests/PHPExif/Data/MetadataTest.php b/tests/PHPExif/Data/MetadataTest.php new file mode 100644 index 0000000..f9deae8 --- /dev/null +++ b/tests/PHPExif/Data/MetadataTest.php @@ -0,0 +1,134 @@ + + */ +class MetadataTest extends \PHPUnit_Framework_TestCase +{ + /** + * @group data + * + * @covers ::__construct + * + * @return void + */ + public function testConstructorSetsInProperties() + { + $exif = new Exif; + $iptc = new Iptc; + $original = new Metadata( + $exif, + $iptc + ); + + foreach (['exif', 'iptc'] as $propName) { + $reflProp = new \ReflectionProperty(Metadata::class, $propName); + $reflProp->setAccessible(true); + + $this->assertSame( + $$propName, + $reflProp->getValue($original) + ); + } + } + + /** + * @group data + * + * @covers ::withExif + * + * @return void + */ + public function testWithExifReturnsClone() + { + $original = new Metadata( + new Exif, + new Iptc + ); + + $newExif = new Exif; + + $other = $original->withExif($newExif); + + $this->assertNotSame( + $original, + $other + ); + } + + /** + * @group data + * + * @covers ::withIptc + * + * @return void + */ + public function testWithIptcReturnsClone() + { + $original = new Metadata( + new Exif, + new Iptc + ); + + $newIptc = new Iptc; + + $other = $original->withIptc($newIptc); + + $this->assertNotSame( + $original, + $other + ); + } + + /** + * @group data + * + * @covers ::getExif + * + * @return void + */ + public function testGetExifReturnsFromProperty() + { + $exif = new Exif; + $iptc = new Iptc; + $original = new Metadata( + $exif, + $iptc + ); + + $this->assertSame( + $exif, + $original->getExif() + ); + } + + /** + * @group data + * + * @covers ::getIptc + * + * @return void + */ + public function testGetIptcReturnsFromProperty() + { + $exif = new Exif; + $iptc = new Iptc; + $original = new Metadata( + $exif, + $iptc + ); + + $this->assertSame( + $iptc, + $original->getIptc() + ); + } +} From 22d5ea30afbeede47e592a3c377fbba5b3ae4241 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Tue, 29 Mar 2016 20:29:14 +0200 Subject: [PATCH 50/51] Unit tests for Exif data class Signed-off-by: Tom Van Herreweghe --- src/PHPExif/Data/Exif.php | 6 +- tests/PHPExif/Data/ExifTest.php | 111 ++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 tests/PHPExif/Data/ExifTest.php diff --git a/src/PHPExif/Data/Exif.php b/src/PHPExif/Data/Exif.php index d4b1040..84194a2 100644 --- a/src/PHPExif/Data/Exif.php +++ b/src/PHPExif/Data/Exif.php @@ -24,7 +24,7 @@ final class Exif implements ExifInterface { /** - * @var string + * @var Aperture */ private $aperture; @@ -56,6 +56,10 @@ public function toArray($withEmpty = true) self::class ); + if (!$withEmpty) { + return array_filter($data); + } + return $data; } } diff --git a/tests/PHPExif/Data/ExifTest.php b/tests/PHPExif/Data/ExifTest.php new file mode 100644 index 0000000..1261745 --- /dev/null +++ b/tests/PHPExif/Data/ExifTest.php @@ -0,0 +1,111 @@ + + */ +class ExifTest extends \PHPUnit_Framework_TestCase +{ + /** + * @group data + * + * @covers ::toArray + * + * @return void + */ + public function testToArrayReturnsListOfData() + { + $properties = [ + ExifInterface::APERTURE => null, + ]; + + $exif = new Exif; + + $this->assertEquals( + $properties, + $exif->toArray() + ); + } + + /** + * @group data + * + * @covers ::toArray + * + * @return void + */ + public function testToArrayFiltersEmpty() + { + $properties = []; + + $exif = new Exif; + + $this->assertEquals( + $properties, + $exif->toArray(false) + ); + } + + /** + * @group data + * + * @covers ::withAperture + * + * @return void + */ + public function testWithApertureReturnsClone() + { + $value = Aperture::fromFocalLength('f/8.0'); + + $exif = new Exif; + $other = $exif->withAperture($value); + + $this->assertInstanceOf( + Exif::class, + $other + ); + $this->assertNotSame( + $exif, + $other + ); + $this->assertEmpty($exif->getAperture()); + } + + /** + * @group data + * + * @covers ::getAperture + * + * @return void + */ + public function testGetApertureReturnsFromProperty() + { + $exif = new Exif; + $value = 'foo'; + + $reflProp = new \ReflectionProperty( + Exif::class, + 'aperture' + ); + $reflProp->setAccessible(true); + + $this->assertEmpty($exif->getAperture()); + + $reflProp->setValue( + $exif, + $value + ); + + $this->assertEquals( + $value, + $exif->getAperture() + ); + } +} From 9334ae333ae4a9cc84034919eaf14994399d71c4 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 6 Apr 2016 08:34:55 +0200 Subject: [PATCH 51/51] Implemented getMapper Signed-off-by: Tom Van Herreweghe --- .../Adapter/Native/NativeAdapterConfig.php | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php index a3fbf27..205f769 100644 --- a/src/PHPExif/Adapter/Native/NativeAdapterConfig.php +++ b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php @@ -14,6 +14,10 @@ use PHPExif\Adapter\AdapterConfig; use PHPExif\Adapter\HasMapper; use PHPExif\Adapter\MapperAccessorTrait; +use PHPExif\Adapter\Native\Mapper\Exif as ExifMappers; +use PHPExif\Adapter\Native\Mapper\ExifMapper; +use PHPExif\Adapter\Native\Mapper\Iptc as IptcMappers; +use PHPExif\Adapter\Native\Mapper\IptcMapper; use PHPExif\Adapter\Native\Reader; use PHPExif\Adapter\Native\ReaderConfig; @@ -103,4 +107,33 @@ private function getReader() return $reader; } + + /** + * {@inheritDoc} + */ + public function getMapper() + { + $exifMapper = new ExifMapper(); + $exifMapper->registerFieldMapers( + [ + new ExifMappers\ApertureFieldMapper, + ] + ); + + $iptcMapper = new IptcMapper(); + $iptcMapper->registerFieldMapers( + [ + ] + ); + + $mapper = new Mapper(); + $mapper->registerFieldMappers( + [ + $exifMapper, + $iptcMapper, + ] + ); + + return $mapper; + } }