diff --git a/.coveralls.yml b/.coveralls.yml index 6b74c21..7a18ce2 100644 --- a/.coveralls.yml +++ b/.coveralls.yml @@ -1 +1 @@ -src_dir: lib +src_dir: src diff --git a/.travis.yml b/.travis.yml index b6272df..45c15fe 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,16 @@ language: php -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - matrix: - allow_failures: + 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 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2059618..7330a5a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,18 @@ CHANGELOG ===== +1.0.0 +----- + +* 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/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..aac21d4 100755 --- a/README.md +++ b/README.md @@ -1,35 +1,28 @@ -# [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=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. 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. -## Supported tools - -* Native PHP functionality (exif_read_data, iptcparse) -* [Exiftool](http://www.sno.phy.queensu.ca/~phil/exiftool) adapter (wrapper for the exiftool binary) +## Minimum requirements -## Installation (composer) +* 0.x branch: PHP 5.3 +* 1.x branch: PHP 5.6 -```json -"miljar/php-exif": "~0.5.0" -``` +See [http://php.net/supported-versions.php](http://php.net/supported-versions.php) for reason. +## Supported tools -## Usage +* Native PHP functionality (exif_read_data, iptcparse) +* @todo: [Exiftool](http://www.sno.phy.queensu.ca/~phil/exiftool) adapter (wrapper for the exiftool binary) -[Before v0.3.0](Resources/doc/usage_0.2.1.md) +## Documentation -[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 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 d0710d3..27adf6f 100755 --- a/composer.json +++ b/composer.json @@ -12,21 +12,23 @@ ], "keywords": ["EXIF", "IPTC", "jpeg", "tiff", "exiftool"], "require": { - "php": ">=5.3.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*", - "satooshi/php-coveralls": "~0.6", - "phpmd/phpmd": "~2.2", - "sebastian/phpcpd": "1.4.*@stable", - "squizlabs/php_codesniffer": "1.4.*@stable" + "phpmd/phpmd": "~2.3.0", + "squizlabs/php_codesniffer": "~2.0", + "phpunit/phpunit": "~5.2.0", + "satooshi/php-coveralls": "~1.0.0", + "mockery/mockery": "^0.9.4" }, "suggest": { "lib-exiftool": "Use perl lib exiftool as adapter" }, + "minimum-stability": "dev", "autoload": { - "psr-0": { - "PHPExif": "lib/" - } + "psr-4": { "PHPExif\\": "src/PHPExif/" } + }, + "autoload-dev": { + "psr-4": { "Tests\\PHPExif\\": "tests/PHPExif/" } } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 499bdee..c248626 100644 --- a/composer.lock +++ b/composer.lock @@ -1,24 +1,79 @@ { "_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", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1eb0d80e545f6ba06a71ff8a967d3c2e", + "hash": "c7b3e5d58c8d21e2c8ad4a6a19504ee4", + "content-hash": "03314d5c6994f0be1ca1a021bcfc4f84", "packages": [], "packages-dev": [ + { + "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": "guzzle/guzzle", - "version": "v3.9.3", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle3.git", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" + "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/b3f5050cb6270c7a728a0b74ac2de50a262b3e02", + "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02", "shasum": "" }, "require": { @@ -100,38 +155,197 @@ "rest", "web service" ], - "time": "2015-03-18 18:23:50" + "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", + "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.0.6", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4" + "reference": "9d816dfa565b9c47685057761acaf432c9e8066a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4", - "reference": "a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/9d816dfa565b9c47685057761acaf432c9e8066a", + "reference": "9d816dfa565b9c47685057761acaf432c9e8066a", "shasum": "" }, "require": { - "symfony/config": ">=2.4", - "symfony/dependency-injection": ">=2.4", - "symfony/filesystem": ">=2.4" + "php": ">=5.3.7", + "symfony/config": "^2.3.0|^3", + "symfony/dependency-injection": "^2.3.0|^3", + "symfony/filesystem": "^2.3.0|^3" }, "require-dev": { - "phpunit/phpunit": "4.*@stable", - "squizlabs/php_codesniffer": "@stable" + "phpunit/phpunit": "^4.4.0,<4.8", + "squizlabs/php_codesniffer": "^2.0.0" }, "bin": [ "src/bin/pdepend" ], "type": "library", "autoload": { - "psr-0": { - "PDepend\\": "src/main/php/" + "psr-4": { + "PDepend\\": "src/main/php/PDepend" } }, "notification-url": "https://packagist.org/downloads/", @@ -139,32 +353,78 @@ "BSD-3-Clause" ], "description": "Official version of pdepend to be handled with Composer", - "time": "2015-03-02 08:06:43" + "time": "2016-02-23 08:20:26" + }, + { + "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.2", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpmd/phpmd.git", - "reference": "7dc4a6b5c07b119ab5da7960b56303fa6855eb84" + "reference": "08b5bcd454a7148579b68931fc500d824afd3bb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/7dc4a6b5c07b119ab5da7960b56303fa6855eb84", - "reference": "7dc4a6b5c07b119ab5da7960b56303fa6855eb84", + "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" + "pdepend/pdepend": "~2.0", + "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "*", - "squizlabs/php_codesniffer": "*" + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.0" }, "bin": [ "src/bin/phpmd" @@ -190,6 +450,12 @@ "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.", @@ -201,50 +467,114 @@ "phpmd", "pmd" ], - "time": "2015-03-26 07:47:05" + "time": "2015-09-24 14:37:49" + }, + { + "name": "phpspec/prophecy", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "b02221e42163be673f9b44a0bc92a8b4907a7c6d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b02221e42163be673f9b44a0bc92a8b4907a7c6d", + "reference": "b02221e42163be673f9b44a0bc92a8b4907a7c6d", + "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.6.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": "2016-02-21 17:41:21" }, { "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": "a58f95ae76fe201b571fad3e8370a50c4368678c" }, "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/a58f95ae76fe201b571fad3e8370a50c4368678c", + "reference": "a58f95ae76fe201b571fad3e8370a50c4368678c", "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" + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0|~2.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*@dev" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~5" }, "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": "3.2.x-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -262,35 +592,37 @@ "testing", "xunit" ], - "time": "2014-09-02 10:13:14" + "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" ], @@ -307,20 +639,20 @@ "filesystem", "iterator" ], - "time": "2013-10-10 15:34:57" + "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { @@ -329,20 +661,17 @@ "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -351,20 +680,20 @@ "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1.0.5" + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" }, "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/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", "shasum": "" }, "require": { @@ -373,13 +702,10 @@ "type": "library", "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -395,49 +721,48 @@ "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2015-06-21 08:01:12" }, { "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": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644" }, "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/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.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 +770,63 @@ "keywords": [ "tokenizer" ], - "time": "2014-03-03 05:10:30" + "time": "2015-09-23 14:46:55" }, { "name": "phpunit/phpunit", - "version": "3.7.38", + "version": "5.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" + "reference": "dbd80d79c7271ff42af453c8a1b387691b555f9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/dbd80d79c7271ff42af453c8a1b387691b555f9a", + "reference": "dbd80d79c7271ff42af453c8a1b387691b555f9a", "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", - "symfony/yaml": "~2.0" - }, - "require-dev": { - "pear-pear.php.net/pear": "1.9.4" + "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.6", + "phpunit/phpunit-mock-objects": ">=3.0.5", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", + "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" }, "bin": [ - "composer/bin/phpunit" + "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.7.x-dev" + "dev-master": "5.2.x-dev" } }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], "license": [ "BSD-3-Clause" ], @@ -512,45 +838,52 @@ } ], "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": "2016-02-23 11:55:17" }, { "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": "c4dd0c9e7fcbf53c6aa48012902be692318c7566" }, "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/c4dd0c9e7fcbf53c6aa48012902be692318c7566", + "reference": "c4dd0c9e7fcbf53c6aa48012902be692318c7566", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" + "doctrine/instantiator": "^1.0.2", + "php": ">=5.6", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~5" }, "suggest": { "ext-soap": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -567,26 +900,34 @@ "mock", "xunit" ], - "time": "2013-01-13 10:24:48" + "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", - "reference": "1.0.0" + "url": "https://github.com/php-fig/log.git", + "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e" }, "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/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/", @@ -600,58 +941,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": "v0.6.1" + "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c" }, "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/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/", @@ -673,27 +1005,34 @@ "github", "test" ], - "time": "2013-05-04 08:07:33" + "time": "2016-01-20 17:35:46" }, { - "name": "sebastian/finder-facade", - "version": "1.1.0", + "name": "sebastian/code-unit-reverse-lookup", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/finder-facade.git", - "reference": "1.1.0" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" }, "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/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", "shasum": "" }, "require": { - "symfony/finder": ">=2.2.0", - "theseer/fdomdocument": ">=1.3.1" + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -706,45 +1045,44 @@ "authors": [ { "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": "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/phpcpd", - "version": "1.4.3", + "name": "sebastian/comparator", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpcpd.git", - "reference": "1.4.3" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" }, "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/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", "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" + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" }, - "bin": [ - "composer/bin/phpcpd" - ], "type": "library", - "autoload": { - "classmap": [ - "src/" + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -752,31 +1090,58 @@ "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": "Copy/Paste Detector (CPD) for PHP code.", - "homepage": "https://github.com/sebastianbergmann/phpcpd", - "time": "2013-07-30 14:37:42" + "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/version", - "version": "1.0.4", + "name": "sebastian/diff", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", + "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/" @@ -787,67 +1152,51 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "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": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" }, { - "name": "squizlabs/php_codesniffer", - "version": "1.4.8", + "name": "sebastian/environment", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d26daa8096ad2c8758677f0352597f8cda4722e0" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d26daa8096ad2c8758677f0352597f8cda4722e0", - "reference": "d26daa8096ad2c8758677f0352597f8cda4722e0", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=5.1.2" + "php": ">=5.3.3" }, - "suggest": { - "phpunit/php-timer": "dev-master" + "require-dev": { + "phpunit/phpunit": "~4.4" }, - "bin": [ - "scripts/phpcs" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-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,627 +1205,798 @@ ], "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": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ - "phpcs", - "standards" + "Xdebug", + "environment", + "hhvm" ], - "time": "2013-11-25 22:07:04" + "time": "2016-02-26 18:40:46" }, { - "name": "symfony/config", - "version": "v2.6.5", - "target-dir": "Symfony/Component/Config", + "name": "sebastian/exporter", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/Config.git", - "reference": "7a47189c7667ca69bcaafd19ef8a8941db449a2c" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "f88f8936517d54ae6d589166810877fb2015d0a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/7a47189c7667ca69bcaafd19ef8a8941db449a2c", - "reference": "7a47189c7667ca69bcaafd19ef8a8941db449a2c", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f88f8936517d54ae6d589166810877fb2015d0a2", + "reference": "f88f8936517d54ae6d589166810877fb2015d0a2", "shasum": "" }, "require": { "php": ">=5.3.3", - "symfony/filesystem": "~2.3" + "sebastian/recursion-context": "~1.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Config\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.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": "Symfony Config Component", - "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" + "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": "symfony/console", - "version": "v2.6.5", - "target-dir": "Symfony/Component/Console", + "name": "sebastian/global-state", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/symfony/Console.git", - "reference": "53f86497ccd01677e22435cfb7262599450a90d1" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/53f86497ccd01677e22435cfb7262599450a90d1", - "reference": "53f86497ccd01677e22435cfb7262599450a90d1", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.1" + "phpunit/phpunit": "~4.2" }, "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/process": "" + "ext-uopz": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Console\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Symfony Console Component", - "homepage": "http://symfony.com", - "time": "2015-03-13 17:37:22" + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" }, { - "name": "symfony/dependency-injection", - "version": "v2.6.5", - "target-dir": "Symfony/Component/DependencyInjection", + "name": "sebastian/recursion-context", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "a49245b2beebe332924561c30772b16e1d32f13a" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/a49245b2beebe332924561c30772b16e1d32f13a", - "reference": "a49245b2beebe332924561c30772b16e1d32f13a", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", + "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "conflict": { - "symfony/expression-language": "<2.6" - }, "require-dev": { - "symfony/config": "~2.2", - "symfony/expression-language": "~2.6", - "symfony/phpunit-bridge": "~2.7", - "symfony/yaml": "~2.1" - }, - "suggest": { - "symfony/config": "", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\DependencyInjection\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Symfony DependencyInjection Component", - "homepage": "http://symfony.com", - "time": "2015-03-17 12:44:40" + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-01-28 05:39:29" }, { - "name": "symfony/event-dispatcher", - "version": "v2.6.5", - "target-dir": "Symfony/Component/EventDispatcher", + "name": "sebastian/resource-operations", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/70f7c8478739ad21e3deef0d977b38c77f1fb284", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.6.0" }, - "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" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "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": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + }, + "dist": { + "type": "zip", + "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.6-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\EventDispatcher\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Symfony EventDispatcher Component", - "homepage": "http://symfony.com", - "time": "2015-03-13 17:37:22" + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-02-04 12:56:52" }, { - "name": "symfony/filesystem", - "version": "v2.6.5", - "target-dir": "Symfony/Component/Filesystem", + "name": "squizlabs/php_codesniffer", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/Filesystem.git", - "reference": "fdc5f151bc2db066b51870d5bea3773d915ced0b" + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "be0a7044ec8f664c07f117e86633250122af6dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/fdc5f151bc2db066b51870d5bea3773d915ced0b", - "reference": "fdc5f151bc2db066b51870d5bea3773d915ced0b", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/fd4cddc0663f216c4b9d9f3cd5d52bc08ab3e951", + "reference": "be0a7044ec8f664c07f117e86633250122af6dbf", "shasum": "" }, "require": { - "php": ">=5.3.3" + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "phpunit/phpunit": "~4.0" }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.x-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Filesystem\\": "" - } + "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": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Greg Sherwood", + "role": "lead" } ], - "description": "Symfony Filesystem Component", - "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" + "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-25 21:37:34" }, { - "name": "symfony/finder", - "version": "v2.6.5", - "target-dir": "Symfony/Component/Finder", + "name": "symfony/config", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/Finder.git", - "reference": "bebc7479c566fa4f14b9bcef9e32e719eabec74e" + "url": "https://github.com/symfony/config.git", + "reference": "f1f7ccf4c17454cf14f43178624c4890cba788d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/bebc7479c566fa4f14b9bcef9e32e719eabec74e", - "reference": "bebc7479c566fa4f14b9bcef9e32e719eabec74e", + "url": "https://api.github.com/repos/symfony/config/zipball/f1f7ccf4c17454cf14f43178624c4890cba788d8", + "reference": "f1f7ccf4c17454cf14f43178624c4890cba788d8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9", + "symfony/filesystem": "~2.8|~3.0" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.1-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Finder\\": "" - } + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", - "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2016-02-23 16:17:05" }, { - "name": "symfony/stopwatch", - "version": "v2.6.5", - "target-dir": "Symfony/Component/Stopwatch", + "name": "symfony/console", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/Stopwatch.git", - "reference": "ba4e774f71e2ce3e3f65cabac4031b9029972af5" + "url": "https://github.com/symfony/console.git", + "reference": "200f109d77649eac204aee729cfc8760f02b3ade" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/ba4e774f71e2ce3e3f65cabac4031b9029972af5", - "reference": "ba4e774f71e2ce3e3f65cabac4031b9029972af5", + "url": "https://api.github.com/repos/symfony/console/zipball/dad9b258d9249b5b4bd504a5ee0483c7a5906660", + "reference": "200f109d77649eac204aee729cfc8760f02b3ade", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "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": "2.6-dev" + "dev-master": "3.1-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Stopwatch\\": "" - } + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Stopwatch Component", - "homepage": "http://symfony.com", - "time": "2015-02-24 11:52:21" + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2016-02-28 16:28:07" }, { - "name": "symfony/yaml", - "version": "v2.6.5", - "target-dir": "Symfony/Component/Yaml", + "name": "symfony/dependency-injection", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "0cd8e72071e46e15fc072270ae39ea1b66b10a9d" + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "c6c4ab94df002d6f3648b488ca96727c4b9b2df8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/0cd8e72071e46e15fc072270ae39ea1b66b10a9d", - "reference": "0cd8e72071e46e15fc072270ae39ea1b66b10a9d", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9d54eec130500072f3a1939ca4606de1428469c3", + "reference": "c6c4ab94df002d6f3648b488ca96727c4b9b2df8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/config": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/yaml": "~2.8|~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": "2.6-dev" + "dev-master": "3.1-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Yaml\\": "" - } + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Yaml Component", - "homepage": "http://symfony.com", - "time": "2015-03-12 10:28:44" + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2016-02-28 16:50:15" }, { - "name": "theseer/fdomdocument", - "version": "1.6.0", + "name": "symfony/event-dispatcher", + "version": "2.8.x-dev", "source": { "type": "git", - "url": "https://github.com/theseer/fDOMDocument.git", - "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d08cf070350f884c63fc9078d27893c2ab6c7cef", - "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/78c468665c9568c3faaa9c416a7134308f2d85c3", + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3", "shasum": "" }, "require": { - "ext-dom": "*", - "lib-libxml": "*", - "php": ">=5.3.3" + "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/stopwatch": "~2.3|~3.0.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "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" + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2016-01-27 05:14:19" }, { - "name": "zetacomponents/base", - "version": "1.9", + "name": "symfony/filesystem", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/zetacomponents/Base.git", - "reference": "f20df24e8de3e48b6b69b2503f917e457281e687" + "url": "https://github.com/symfony/filesystem.git", + "reference": "c8a0b857efc7c19b087129a7d7555f866d61b557" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zetacomponents/Base/zipball/f20df24e8de3e48b6b69b2503f917e457281e687", - "reference": "f20df24e8de3e48b6b69b2503f917e457281e687", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c8a0b857efc7c19b087129a7d7555f866d61b557", + "reference": "c8a0b857efc7c19b087129a7d7555f866d61b557", "shasum": "" }, - "require-dev": { - "zetacomponents/unit-test": "*" + "require": { + "php": ">=5.5.9" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, "autoload": { - "classmap": [ - "src" + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "MIT" ], "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": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Alexandru Stanoi" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "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" + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2016-02-23 16:17:05" }, { - "name": "zetacomponents/console-tools", - "version": "1.7", + "name": "symfony/polyfill-mbstring", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/zetacomponents/ConsoleTools.git", - "reference": "30d67e9d04f458ac8cae4c49e50f81061460ff2c" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "1289d16209491b584839022f29257ad859b8532d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zetacomponents/ConsoleTools/zipball/30d67e9d04f458ac8cae4c49e50f81061460ff2c", - "reference": "30d67e9d04f458ac8cae4c49e50f81061460ff2c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", + "reference": "1289d16209491b584839022f29257ad859b8532d", "shasum": "" }, "require": { - "zetacomponents/base": "~1.8" + "php": ">=5.3.3" }, - "require-dev": { - "zetacomponents/unit-test": "*" + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, "autoload": { - "classmap": [ - "src" + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "MIT" ], "authors": [ { - "name": "Sergey Alexeev" - }, - { - "name": "Sebastian Bergmann" - }, - { - "name": "Jan Borsodi" - }, - { - "name": "Raymond Bosman" - }, - { - "name": "Frederik Holljen" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Kore Nordmann" + "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-20 09:13:37" + }, + { + "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": "Derick Rethans" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Vadym Savchuk" + "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": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "939b8e10c4e0e1135144fb09e12a3d32ff129e4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ab0314f7544d600ea7917f02cdad774358b81113", + "reference": "939b8e10c4e0e1135144fb09e12a3d32ff129e4a", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "name": "Tobias Schlitt" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Alexandru Stanoi" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "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" + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-02-28 10:09:55" } ], "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": { - "php": ">=5.3.0" + "php": "^5.6 || ^7.0" }, "platform-dev": [] } 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/phpunit.xml.dist b/phpunit.xml.dist index 7470936..76995b9 100755 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -11,12 +11,14 @@ - ./lib + ./src - ./autoload.php *Interface.php + + ./vendor + 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/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..d39daec --- /dev/null +++ b/src/PHPExif/Adapter/AdapterConfig.php @@ -0,0 +1,35 @@ + + * @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'; + + /** + * 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/lib/PHPExif/Mapper/MapperInterface.php b/src/PHPExif/Adapter/MapperInterface.php similarity index 71% rename from lib/PHPExif/Mapper/MapperInterface.php rename to src/PHPExif/Adapter/MapperInterface.php index 5f5097e..3552532 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\MetadataInterface; /** - * 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 @@ -24,10 +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 array + * + * @return MetadataInterface */ - public function mapRawData(array $data); + public function map(array $data); } diff --git a/src/PHPExif/Adapter/Native/Mapper.php b/src/PHPExif/Adapter/Native/Mapper.php new file mode 100644 index 0000000..06d6c5e --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper.php @@ -0,0 +1,86 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +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; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +class Mapper implements MapperInterface, ArrayMapper +{ + use FieldMapperTrait; + + const FIELD_EXIF = 'exif'; + const FIELD_IPTC = 'iptc'; + + /** + * {@inheritDoc} + */ + public function map(array $data) + { + $output = new Metadata( + new Exif, + new Iptc + ); + + $this->mapArray($data, $output); + + return $output; + } + + /** + * {@inheritDoc} + */ + public function mapArray(array $input, &$output) + { + $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) + { + $iptcMapper = $this->getFieldMapper(self::FIELD_IPTC); + $iptcMapper->mapField(self::FIELD_IPTC, $input, $output); + } + + /** + * Maps the EXIF data + * + * @param array $input + * @param object $output + * + * @return void + */ + private function mapExif($input, &$output) + { + $exifMapper = $this->getFieldMapper(self::FIELD_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 new file mode 100644 index 0000000..75c0c03 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper/Exif/ApertureFieldMapper.php @@ -0,0 +1,52 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + * @codeCoverageIgnore + */ + +namespace PHPExif\Adapter\Native\Mapper\Exif; + +use PHPExif\Data\ExifInterface; +use PHPExif\Data\Exif\Aperture; +use PHPExif\Mapper\FieldMapper; + +/** + * 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); + + $aperture = Aperture::fromFocalLength( + $input['COMPUTED']['ApertureFNumber'] + ); + + $output = $output->withAperture($aperture); + } +} 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..b717b79 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper/ExifMapper.php @@ -0,0 +1,91 @@ + + * @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\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; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +class ExifMapper implements ArrayMapper, FieldMapper +{ + use FieldMapperTrait; + + /** + * {@inheritDoc} + */ + public function getSupportedFields() + { + return array( + Mapper::FIELD_EXIF, + ); + } + + /** + * {@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) { + try { + $fieldMapper = $this->getFieldMapper($name); + } catch (MapperNotRegisteredException $e) { + // silently ignore missing FieldMapper + continue; + } + + $fieldMapper->mapField( + $name, + $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 new file mode 100644 index 0000000..5ef495d --- /dev/null +++ b/src/PHPExif/Adapter/Native/Mapper/IptcMapper.php @@ -0,0 +1,91 @@ + + * @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\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; + +/** + * Mapper + * + * @category PHPExif + * @package Adapter + */ +class IptcMapper implements ArrayMapper, FieldMapper +{ + use FieldMapperTrait; + + /** + * {@inheritDoc} + */ + public function getSupportedFields() + { + return array( + Mapper::FIELD_IPTC, + ); + } + + /** + * {@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) { + try { + $fieldMapper = $this->getFieldMapper($name); + } catch (MapperNotRegisteredException $e) { + // silently ignore missing FieldMapper + continue; + } + + $fieldMapper->mapField( + $name, + $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 new file mode 100644 index 0000000..205f769 --- /dev/null +++ b/src/PHPExif/Adapter/Native/NativeAdapterConfig.php @@ -0,0 +1,139 @@ + + * @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\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; + +/** + * NativeAdapterConfig + * + * @category PHPExif + * @package Adapter + */ +final class NativeAdapterConfig implements AdapterConfig, HasMapper +{ + use MapperAccessorTrait; + + 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] + ), + $this->getMapper() + ); + + 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; + } +} diff --git a/src/PHPExif/Adapter/Native/Reader.php b/src/PHPExif/Adapter/Native/Reader.php new file mode 100644 index 0000000..38e80e2 --- /dev/null +++ b/src/PHPExif/Adapter/Native/Reader.php @@ -0,0 +1,108 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Adapter + */ + +namespace PHPExif\Adapter\Native; + +use PHPExif\Adapter\HasMapper; +use PHPExif\Adapter\MapperAccessorTrait; +use PHPExif\Adapter\MapperInterface; +use PHPExif\Adapter\ReaderInterface; +use PHPExif\Exception\NoExifDataException; +use PHPExif\Exception\UnknownAdapterTypeException; + +/** + * Reader class + * + * @category PHPExif + * @package Adapter + */ +final class Reader implements ReaderInterface, HasMapper +{ + use MapperAccessorTrait; + + /** + * @var ReaderConfig + */ + private $configuration; + + /** + * @param ReaderConfig $configuration + */ + public function __construct( + ReaderConfig $configuration, + MapperInterface $mapper + ) { + $this->configuration = $configuration; + $this->setMapper($mapper); + } + + /** + * {@inheritDoc} + * + * @throws NoExifDataException + */ + public function getMetadataFromFile($filePath) + { + $data = @exif_read_data( + $filePath, + $this->configuration->getSections(), + false, // flat array + false // no thumbnail + ); + + if (false === $data) { + throw NoExifDataException::fromFile($filePath); + } + + $this->augmentDataWithIptcRawData($filePath, $data); + + // map the data: + $mapper = $this->getMapper(); + $readerResult = $mapper->map($data); + + return $readerResult; + } + + /** + * Adds data from iptcparse to the original raw EXIF data + * + * @param string $filePath + * @param array $data + * + * @return void + */ + private function augmentDataWithIptcRawData($filePath, array &$data) + { + if (!$this->configuration->isParseRawIptcData()) { + return; + } + + getimagesize($filePath, $info); + + 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); + } + + // Merge with original raw Exif data + $data = array_merge( + $data, + $iptcRawData + ); + } +} diff --git a/src/PHPExif/Adapter/Native/ReaderConfig.php b/src/PHPExif/Adapter/Native/ReaderConfig.php new file mode 100644 index 0000000..e5b05c3 --- /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; + +/** + * 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 new file mode 100644 index 0000000..4370417 --- /dev/null +++ b/src/PHPExif/Adapter/ReaderInterface.php @@ -0,0 +1,50 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Adapter; + +use PHPExif\Data\MetadataInterface; + +/** + * ReaderInterface + * + * Public API for reading EXIF data + * + * @category PHPExif + * @package Exif + */ +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 + * + * @param string $filePath + * + * @return MetadataInterface + */ + public function getMetadataFromFile($filePath); +} 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/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/Data/Exif.php b/src/PHPExif/Data/Exif.php new file mode 100644 index 0000000..84194a2 --- /dev/null +++ b/src/PHPExif/Data/Exif.php @@ -0,0 +1,65 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +use PHPExif\Data\Exif\Aperture; + +/** + * Exif class + * + * Container for EXIF data + * + * @category PHPExif + * @package Exif + */ +final class Exif implements ExifInterface +{ + /** + * @var Aperture + */ + private $aperture; + + /** + * {@inheritDoc} + */ + public function getAperture() + { + return $this->aperture; + } + + /** + * {@inheritDoc} + */ + public function withAperture(Aperture $aperture) + { + $new = clone $this; + $new->aperture = $aperture; + + return $new; + } + + /** + * {@inheritDoc} + */ + public function toArray($withEmpty = true) + { + $data = get_class_vars( + self::class + ); + + if (!$withEmpty) { + return array_filter($data); + } + + return $data; + } +} diff --git a/src/PHPExif/Data/Exif/Aperture.php b/src/PHPExif/Data/Exif/Aperture.php new file mode 100644 index 0000000..778dbfd --- /dev/null +++ b/src/PHPExif/Data/Exif/Aperture.php @@ -0,0 +1,91 @@ + + * @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 = (float) $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 sprintf( + 'f/%1.1f', + $this->fNumber + ); + } +} diff --git a/src/PHPExif/Data/ExifInterface.php b/src/PHPExif/Data/ExifInterface.php new file mode 100644 index 0000000..b78a71e --- /dev/null +++ b/src/PHPExif/Data/ExifInterface.php @@ -0,0 +1,77 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + */ + +namespace PHPExif\Data; + +use PHPExif\Data\Exif\Aperture; + +/** + * 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'; + + /** + * Accessor for the aperture + * + * @return Aperture + */ + public function getAperture(); + + /** + * Returns new instance with updated aperture + * + * @param Aperture $aperture + * + * @return ExifInterface + */ + public function withAperture(Aperture $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 new file mode 100644 index 0000000..147759b --- /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 = array()) + { + foreach ($data as $key => $value) { + if (!array_key_exists($key, self::$iptcMapping)) { + continue; + } + + $this->$key = $value; + } + } + + /** + * {@inheritDoc} + */ + public function toArray($withEmpty = true) + { + $data = array(); + $keys = array_keys(self::$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..3c1cf65 --- /dev/null +++ b/src/PHPExif/Data/IptcInterface.php @@ -0,0 +1,160 @@ + + * @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/Data/Metadata.php b/src/PHPExif/Data/Metadata.php new file mode 100644 index 0000000..ce05129 --- /dev/null +++ b/src/PHPExif/Data/Metadata.php @@ -0,0 +1,83 @@ + + * @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; + + /** + * Constructor + * + * @param ExifInterface $exif + * @param IptcInterface $iptc + */ + public function __construct(ExifInterface $exif, IptcInterface $iptc) + { + $this->exif = $exif; + $this->iptc = $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() + { + return $this->exif; + } + + /** + * {@inheritDoc} + */ + public function getIptc() + { + 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(); +} 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/lib/PHPExif/Adapter/NoAdapterException.php b/src/PHPExif/Exception/Adapter/NoMapperSetException.php similarity index 50% rename from lib/PHPExif/Adapter/NoAdapterException.php rename to src/PHPExif/Exception/Adapter/NoMapperSetException.php index 8a2b011..288bfc1 100644 --- a/lib/PHPExif/Adapter/NoAdapterException.php +++ b/src/PHPExif/Exception/Adapter/NoMapperSetException.php @@ -1,28 +1,22 @@ * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif - * @package Reader - * @codeCoverageIgnore + * @package Exception */ -namespace PHPExif\Adapter; - -use Exception; +namespace PHPExif\Exception\Adapter; /** - * PHP Exif Reader Adapter - * - * Defines the interface for reader adapters + * NoMapperSetException * * @category PHPExif - * @package Reader + * @package Exception */ -class NoAdapterException extends Exception +class NoMapperSetException extends \RuntimeException { - //empty } 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 + ) + ); + } +} diff --git a/src/PHPExif/Exception/InterruptException.php b/src/PHPExif/Exception/InterruptException.php new file mode 100644 index 0000000..6e5ece3 --- /dev/null +++ b/src/PHPExif/Exception/InterruptException.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/Mapper/MapperNotRegisteredException.php b/src/PHPExif/Exception/Mapper/MapperNotRegisteredException.php new file mode 100644 index 0000000..0d41305 --- /dev/null +++ b/src/PHPExif/Exception/Mapper/MapperNotRegisteredException.php @@ -0,0 +1,38 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + * @codeCoverageIgnore + */ + +namespace PHPExif\Exception\Mapper; + +/** + * MapperNotRegisteredException + * + * @category PHPExif + * @package Exif + */ +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/Exception/Mapper/UnsupportedOutputException.php b/src/PHPExif/Exception/Mapper/UnsupportedOutputException.php new file mode 100644 index 0000000..2dfabd4 --- /dev/null +++ b/src/PHPExif/Exception/Mapper/UnsupportedOutputException.php @@ -0,0 +1,38 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + * @codeCoverageIgnore + */ + +namespace PHPExif\Exception\Mapper; + +/** + * UnsupportedOutputException + * + * @category PHPExif + * @package Exif + */ +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/Exception/NoExifDataException.php b/src/PHPExif/Exception/NoExifDataException.php new file mode 100644 index 0000000..25f2dd3 --- /dev/null +++ b/src/PHPExif/Exception/NoExifDataException.php @@ -0,0 +1,38 @@ + + * @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..59fb2fb --- /dev/null +++ b/src/PHPExif/Exception/UnknownAdapterTypeException.php @@ -0,0 +1,57 @@ + + * @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/Mapper/ArrayMapper.php b/src/PHPExif/Mapper/ArrayMapper.php new file mode 100644 index 0000000..cf6d6d0 --- /dev/null +++ b/src/PHPExif/Mapper/ArrayMapper.php @@ -0,0 +1,64 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + * @codeCoverageIgnore + */ + +namespace PHPExif\Mapper; + +use PHPExif\Exception\Mapper\MapperNotRegisteredException; + +/** + * ArrayMapper + * + * Public API for mapping an array of EXIF data + * to and from Exif + * + * @category PHPExif + * @package Exif + */ +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/Mapper/FieldMapper.php b/src/PHPExif/Mapper/FieldMapper.php new file mode 100644 index 0000000..3f2e6aa --- /dev/null +++ b/src/PHPExif/Mapper/FieldMapper.php @@ -0,0 +1,45 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + * @codeCoverageIgnore + */ + +namespace PHPExif\Mapper; + +use PHPExif\Data\MetadataInterface; + +/** + * FieldMapper + * + * Public API for mapping fields of EXIF data + * to and from Exif + * + * @category PHPExif + * @package Exif + */ +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); +} diff --git a/src/PHPExif/Mapper/FieldMapperTrait.php b/src/PHPExif/Mapper/FieldMapperTrait.php new file mode 100644 index 0000000..d38429a --- /dev/null +++ b/src/PHPExif/Mapper/FieldMapperTrait.php @@ -0,0 +1,76 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Exif + * @codeCoverageIgnore + */ + +namespace PHPExif\Mapper; + +use PHPExif\Exception\Mapper\MapperNotRegisteredException; + +/** + * Mapper + * + * @category PHPExif + * @package Exif + */ +trait FieldMapperTrait +{ + /** + * @var FieldMapper[] + */ + private $fieldMappers = array(); + + /** + * {@inheritDoc} + */ + public function registerFieldMappers(array $fieldMappers) + { + foreach ($fieldMappers as $fieldMapper) { + $this->registerFieldMapper($fieldMapper); + } + } + + /** + * Registers given FieldMapper instance + * Allows overwriting an already existing mapper for a given field + * + * @param FieldMapper $fieldMapper + * + * @return void + */ + public function registerFieldMapper(FieldMapper $fieldMapper) + { + $targetFields = $fieldMapper->getSupportedFields(); + + foreach ($targetFields as $fieldName) { + $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); + } +} 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; + } +} 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'] + ); + } +} 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/Native/MapperTest.php b/tests/PHPExif/Adapter/Native/MapperTest.php new file mode 100644 index 0000000..d3fdf66 --- /dev/null +++ b/tests/PHPExif/Adapter/Native/MapperTest.php @@ -0,0 +1,262 @@ + + */ +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() + { + $input = array(); + $output = new Metadata( + new Exif, + new Iptc + ); + + $mapper = new Mapper; + + foreach (array(Mapper::FIELD_EXIF, MAPPER::FIELD_IPTC) as $field) { + $fieldMapper = m::mock(FieldMapper::class . '[getSupportedFields,mapField]'); + $fieldMapper->shouldReceive('getSupportedFields') + ->once() + ->andReturn(array($field)); + $fieldMapper->shouldReceive('mapField') + ->once() + ->with( + $field, + $input, + m::type(Metadata::class) + ) + ->andReturnNull(); + + $mapper->registerFieldMapper($fieldMapper); + } + + $mapper->mapArray($input, $output); + } +} 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/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 + ); + } +} 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() + ); + } +} 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() + ); + } +} diff --git a/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php b/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php new file mode 100644 index 0000000..f2c9ad6 --- /dev/null +++ b/tests/PHPExif/Exception/Adapter/AdapterAlreadyRegisteredExeptionTest.php @@ -0,0 +1,26 @@ + + */ +class AdapterAlreadyRegisteredExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::withName + */ + public function testWithNameReturnsInstance() + { + $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..eeca030 --- /dev/null +++ b/tests/PHPExif/Exception/Adapter/AdapterNotRegisteredExeptionTest.php @@ -0,0 +1,26 @@ + + */ +class AdapterNotRegisteredExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::withName + */ + public function testWithNameReturnsInstance() + { + $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..67dcaaf --- /dev/null +++ b/tests/PHPExif/Exception/Collection/ElementAlreadyExistsExeptionTest.php @@ -0,0 +1,26 @@ + + */ +class ElementAlreadyExistsExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::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..6d9e3e5 --- /dev/null +++ b/tests/PHPExif/Exception/Collection/ElementNotExistsExeptionTest.php @@ -0,0 +1,26 @@ + + */ +class ElementNotExistsExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::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..42f767b --- /dev/null +++ b/tests/PHPExif/Exception/Collection/InvalidElementTypeExeptionTest.php @@ -0,0 +1,26 @@ + + */ +class InvalidElementTypeExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::withExpectedType + */ + public function testWithExpectedTypeReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + InvalidElementTypeException::class, + 'withExpectedType', + array('foo') + ); + } +} 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) + ) + ); + } +} diff --git a/tests/PHPExif/Exception/NoExifDataExceptionTest.php b/tests/PHPExif/Exception/NoExifDataExceptionTest.php new file mode 100644 index 0000000..592238c --- /dev/null +++ b/tests/PHPExif/Exception/NoExifDataExceptionTest.php @@ -0,0 +1,26 @@ + + */ +class NoExifDataExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::fromFile + */ + public function testFromFileReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + NoExifDataException::class, + 'fromFile', + array('foo') + ); + } +} diff --git a/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php new file mode 100644 index 0000000..3487d58 --- /dev/null +++ b/tests/PHPExif/Exception/UnknownAdapterTypeExceptionTest.php @@ -0,0 +1,39 @@ + + */ +class UnknownAdapterTypeExceptionTest extends BaseExceptionTest +{ + /** + * @group exception + * @covers ::forType + */ + public function testForTypeReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + UnknownAdapterTypeException::class, + 'forType', + array('foo') + ); + } + + /** + * @group exception + * @covers ::noInterface + */ + public function testnoInterfaceReturnsInstance() + { + $this->assertNamedConstructorReturnsInstance( + UnknownAdapterTypeException::class, + 'noInterface', + array('foo', 'bar',) + ); + } +} 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/files/dsc_5794.jpg b/tests/files/dsc_5794.jpg deleted file mode 100644 index 6a23451..0000000 Binary files a/tests/files/dsc_5794.jpg and /dev/null differ 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 aa037c7..0000000 Binary files a/tests/files/morning_glory_pool_500.jpg and /dev/null differ