From cabf6a36562ce55e684d727f2ee08ac7d850ced4 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 19:21:12 +0200 Subject: [PATCH 01/37] Add Mutator Hydrator for hydrating Exif objects Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Hydrator/HydratorInterface.php | 33 +++++++++++++ lib/PHPExif/Hydrator/Mutator.php | 56 ++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 lib/PHPExif/Hydrator/HydratorInterface.php create mode 100644 lib/PHPExif/Hydrator/Mutator.php diff --git a/lib/PHPExif/Hydrator/HydratorInterface.php b/lib/PHPExif/Hydrator/HydratorInterface.php new file mode 100644 index 0000000..8f81bdd --- /dev/null +++ b/lib/PHPExif/Hydrator/HydratorInterface.php @@ -0,0 +1,33 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Hydrator + */ + +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 new file mode 100644 index 0000000..52559d1 --- /dev/null +++ b/lib/PHPExif/Hydrator/Mutator.php @@ -0,0 +1,56 @@ + + * @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; + } +} + From 8f6cdc03d90fef6c69b1a4b8f5803ab743028bfe Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 19:21:41 +0200 Subject: [PATCH 02/37] Add separate mappers for mapping data to Exif object format Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Mapper/Exiftool.php | 134 +++++++++++++++++++++ lib/PHPExif/Mapper/MapperInterface.php | 33 ++++++ lib/PHPExif/Mapper/Native.php | 157 +++++++++++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 lib/PHPExif/Mapper/Exiftool.php create mode 100644 lib/PHPExif/Mapper/MapperInterface.php create mode 100644 lib/PHPExif/Mapper/Native.php diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php new file mode 100644 index 0000000..27dbbe2 --- /dev/null +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -0,0 +1,134 @@ + + * @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 = 'Aperture'; + const APPROXIMATEFOCUSDISTANCE = 'ApproximateFocusDistance'; + const ARTIST = 'Artist'; + const CAPTION = 'Caption'; + const CAPTIONABSTRACT = 'Caption-Abstract'; + const COLORSPACE = 'ColorSpace'; + const COPYRIGHT = 'Copyright'; + const CREATIONDATE = 'CreationDate'; + const CREDIT = 'Credit'; + const EXPOSURETIME = 'ExposureTime'; + const FILESIZE = 'FileSize'; + const FOCALLENGTH = 'FocalLength'; + const HEADLINE = 'Headline'; + const IMAGEHEIGHT = 'ImageHeight'; + const IMAGEWIDTH = 'ImageWidth'; + const ISO = 'ISO'; + 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 XRESOLUTION = 'XResolution'; + const YRESOLUTION = 'YResolution'; + + /** + * 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::CAPTIONABSTRACT => Exif::CAPTION, + self::COLORSPACE => Exif::COLORSPACE, + self::COPYRIGHT => Exif::COPYRIGHT, + self::CREATIONDATE => 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, + ); + + /** + * Maps the array of raw source data to the correct + * fields for the \PHPExif\Exif class + * + * @param array $data + * @return void + */ + public function mapRawData(array $data) + { + $mappedData = 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::CREATIONDATE: + $value = DateTime::createFromFormat('Y:m:d H:i:s', $value); + break; + case self::EXPOSURETIME: + $value = '1/' . round(1 / $value); + break; + case self::FOCALLENGTH: + $focalLengthParts = explode(' ', $value); + $value = (int) reset($focalLengthParts); + break; + } + + // set end result + $mappedData[$key] = $value; + } + + return $mappedData; + } +} + diff --git a/lib/PHPExif/Mapper/MapperInterface.php b/lib/PHPExif/Mapper/MapperInterface.php new file mode 100644 index 0000000..234ca06 --- /dev/null +++ b/lib/PHPExif/Mapper/MapperInterface.php @@ -0,0 +1,33 @@ + + * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License + * @category PHPExif + * @package Mapper + */ + +namespace PHPExif\Mapper; + +/** + * PHP Exif Mapper + * + * Defines the interface for data mappers + * + * @category PHPExif + * @package Mapper + */ +interface MapperInterface +{ + /** + * Maps the array of raw source data to the correct + * fields for the \PHPExif\Exif class + * + * @param array $data + * @return void + */ + public function mapRawData(array $data); +} + diff --git a/lib/PHPExif/Mapper/Native.php b/lib/PHPExif/Mapper/Native.php new file mode 100644 index 0000000..ac36580 --- /dev/null +++ b/lib/PHPExif/Mapper/Native.php @@ -0,0 +1,157 @@ + + * @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 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 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'; + + /** + * Maps the ExifTool fields to the fields of + * the \PHPExif\Exif class + * + * @var array + */ + protected $map = array( + //self::SECTION_COMPUTED => array( + self::APERTUREFNUMBER => Exif::APERTURE, + self::FOCUSDISTANCE => Exif::FOCAL_DISTANCE, + self::HEIGHT => Exif::HEIGHT, + self::WIDTH => Exif::WIDTH, + //), + //self::SECTION_IPTC => array( + 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, + ); + + /** + * Maps the array of raw source data to the correct + * fields for the \PHPExif\Exif class + * + * @param array $data + * @return void + */ + public function mapRawData(array $data) + { + $mappedData = array(); + foreach ($data as $field => $value) { + if (is_string($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: + $value = DateTime::createFromFormat('Y:m:d H:i:s', $value); + break; + case self::EXPOSURETIME: + // normalize ExposureTime + // on one test image, it reported "10/300" instead of "1/30" + list($counter, $denominator) = explode('/', $value); + if (intval($counter) !== 1) { + $denominator /= $counter; + } + $value = '1/' . round($denominator); + 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; + } + + // set end result + $mappedData[$key] = $value; + } + + return $mappedData; + } +} + From bf6ad93a31e26d3234bdd69f2dcf3bf7d7cb3c38 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 19:28:11 +0200 Subject: [PATCH 03/37] AdapterAbstract now uses Hydrator for setOptions; Removed obsolete methods Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/AdapterAbstract.php | 110 +++++++++--------- tests/PHPExif/Adapter/AdapterAbstractTest.php | 97 +-------------- 2 files changed, 61 insertions(+), 146 deletions(-) diff --git a/lib/PHPExif/Adapter/AdapterAbstract.php b/lib/PHPExif/Adapter/AdapterAbstract.php index 1e4450f..d4b122e 100644 --- a/lib/PHPExif/Adapter/AdapterAbstract.php +++ b/lib/PHPExif/Adapter/AdapterAbstract.php @@ -11,6 +11,9 @@ namespace PHPExif\Adapter; +use PHPExif\Mapper\MapperInterface; +use PHPExif\Hydrator\HydratorInterface; + /** * PHP Exif Reader Adapter Abstract * @@ -21,6 +24,21 @@ */ abstract class AdapterAbstract implements AdapterInterface { + /** + * @var string + */ + protected $hydratorClass = '\\PHPExif\\Hydrator\\Mutator'; + + /** + * @var \PHPExif\Mapper\MapperInterface + */ + protected $mapper; + + /** + * @var \PHPExif\Hydrator\HydratorInterface + */ + protected $hydrator; + /** * Class constructor * @@ -34,88 +52,76 @@ public function __construct(array $options = array()) } /** - * Set array of options in the current object + * Mutator for the data mapper * - * @param array $options - * @return \PHPExif\Reader\AdapterAbstract + * @param \PHPExif\Mapper\MapperInterface $mapper + * @return \PHPExif\Adapter\AdapterInterface; */ - public function setOptions(array $options) + public function setMapper(MapperInterface $mapper) { - foreach ($options as $property => $value) { - $setter = $this->determinePropertySetter($property); - if (method_exists($this, $setter)) { - $this->$setter($value); - } - } + $this->mapper = $mapper; return $this; } /** - * Detemines the name of the getter method for given property name + * Accessor for the data mapper * - * @param string $property The property to determine the getter for - * @return string The name of the getter method + * @return \PHPExif\Mapper\MapperInterface */ - protected function determinePropertyGetter($property) + public function getMapper() { - $method = 'get' . ucfirst($property); - return $method; + if (null === $this->mapper) { + // lazy load one + $mapper = new $this->mapperClass; + + $this->setMapper($mapper); + } + + return $this->mapper; } /** - * Detemines the name of the setter method for given property name + * Mutator for the hydrator * - * @param string $property The property to determine the setter for - * @return string The name of the setter method + * @param \PHPExif\Hydrator\HydratorInterface $hydrator + * @return \PHPExif\Adapter\AdapterInterface; */ - protected function determinePropertySetter($property) + public function setHydrator(HydratorInterface $hydrator) { - $method = 'set' . ucfirst($property); - return $method; + $this->hydrator = $hydrator; + + return $this; } /** - * Get a list of the class constants prefixed with given $type + * Accessor for the data hydrator * - * @param string $type - * @return array + * @return \PHPExif\Hydrator\HydratorInterface */ - public function getClassConstantsOfType($type) + public function getHydrator() { - $class = new \ReflectionClass(get_called_class()); - $constants = $class->getConstants(); - - $list = array(); - $type = strtoupper($type) . '_'; - foreach ($constants as $key => $value) { - if (strpos($key, $type) === 0) { - $list[$key] = $value; - } + if (null === $this->hydrator) { + // lazy load one + $hydrator = new $this->hydratorClass; + + $this->setHydrator($hydrator); } - return $list; + + return $this->hydrator; } /** - * Returns an array notation of current instance + * Set array of options in the current object * - * @return array + * @param array $options + * @return \PHPExif\Reader\AdapterAbstract */ - public function toArray() + public function setOptions(array $options) { - $rc = new \ReflectionClass(get_class($this)); - $properties = $rc->getProperties(); - $arrResult = array(); - - foreach ($properties as $rp) { - /* @var $rp \ReflectionProperty */ - $getter = $this->determinePropertyGetter($rp->getName()); - if (!method_exists($this, $getter)) { - continue; - } - $arrResult[$rp->getName()] = $this->$getter(); - } + $hydrator = $this->getHydrator(); + $hydrator->hydrate($this, $options); - return $arrResult; + return $this; } } diff --git a/tests/PHPExif/Adapter/AdapterAbstractTest.php b/tests/PHPExif/Adapter/AdapterAbstractTest.php index 97d2794..fd52e37 100644 --- a/tests/PHPExif/Adapter/AdapterAbstractTest.php +++ b/tests/PHPExif/Adapter/AdapterAbstractTest.php @@ -12,97 +12,6 @@ public function setUp() $this->adapter = new \PHPExif\Adapter\Native(); } - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::determinePropertyGetter - */ - public function testDeterminePropertyGetter() - { - $reflMethod = new \ReflectionMethod('\PHPExif\Adapter\Native', 'determinePropertyGetter'); - $reflMethod->setAccessible(true); - - $result = $reflMethod->invoke( - $this->adapter, - 'foo' - ); - - $this->assertEquals('getFoo', $result); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::determinePropertySetter - */ - public function testDeterminePropertySetter() - { - $reflMethod = new \ReflectionMethod('\PHPExif\Adapter\Native', 'determinePropertySetter'); - $reflMethod->setAccessible(true); - - $result = $reflMethod->invoke( - $this->adapter, - 'foo' - ); - - $this->assertEquals('setFoo', $result); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getClassConstantsOfType - */ - public function testGetClassConstantsOfTypeAlwaysReturnsArray() - { - $result = $this->adapter->getClassConstantsOfType('sections'); - $this->assertInternalType('array', $result); - $result = $this->adapter->getClassConstantsOfType('foo'); - $this->assertInternalType('array', $result); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::getClassConstantsOfType - */ - public function testGetClassConstantsOfTypeReturnsCorrectData() - { - $expected = array( - 'SECTIONS_AS_ARRAYS' => \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS, - 'SECTIONS_FLAT' => \PHPExif\Adapter\Native::SECTIONS_FLAT, - ); - $actual = $this->adapter->getClassConstantsOfType('sections'); - $this->assertEquals($expected, $actual); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::toArray - */ - public function testToArrayReturnsPropertiesWithGetters() - { - $expected = array( - 'requiredSections', - 'includeThumbnail', - 'sectionsAsArrays', - ); - $result = $this->adapter->toArray(); - $actual = array_keys($result); - $this->assertEquals($expected, $actual); - } - - /** - * @group adapter - * @covers \PHPExif\Adapter\AdapterAbstract::toArray - */ - public function testToArrayOmmitsPropertiesWithoutGetters() - { - $expected = array( - 'iptcMapping', - ); - $result = $this->adapter->toArray(); - $actual = array_keys($result); - $diff = array_diff($expected, $actual); - $this->assertEquals($expected, $diff); - } - /** * @group adapter * @covers \PHPExif\Adapter\AdapterAbstract::setOptions @@ -127,7 +36,7 @@ public function testSetOptionsCorrectlySetsProperties() $this->adapter->setOptions($expected); foreach ($expected as $key => $value) { - $reflProp = new \ReflectionProperty('\PHPExif\Adapter\Native', $key); + $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key); $reflProp->setAccessible(true); $this->assertEquals($value, $reflProp->getValue($this->adapter)); } @@ -145,7 +54,7 @@ public function testSetOptionsIgnoresPropertiesWithoutSetters() $this->adapter->setOptions($expected); foreach ($expected as $key => $value) { - $reflProp = new \ReflectionProperty('\PHPExif\Adapter\Native', $key); + $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key); $reflProp->setAccessible(true); $this->assertNotEquals($value, $reflProp->getValue($this->adapter)); } @@ -166,7 +75,7 @@ public function testConstructorSetsOptions() $adapter = new \PHPExif\Adapter\Native($expected); foreach ($expected as $key => $value) { - $reflProp = new \ReflectionProperty('\PHPExif\Adapter\Native', $key); + $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key); $reflProp->setAccessible(true); $this->assertEquals($value, $reflProp->getValue($adapter)); } From bb6f4e263099e593bc723f287be6eeb42cb8446e Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 19:28:50 +0200 Subject: [PATCH 04/37] Extracted mapping of ExifTool data to separate mapper & updated Exiftool adapter to use that mapper Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/Exiftool.php | 117 ++++--------------------- tests/PHPExif/Adapter/ExiftoolTest.php | 97 -------------------- 2 files changed, 17 insertions(+), 197 deletions(-) diff --git a/lib/PHPExif/Adapter/Exiftool.php b/lib/PHPExif/Adapter/Exiftool.php index 8e6bbe6..f7169ac 100644 --- a/lib/PHPExif/Adapter/Exiftool.php +++ b/lib/PHPExif/Adapter/Exiftool.php @@ -14,7 +14,6 @@ use PHPExif\Exif; use InvalidArgumentException; use RuntimeException; -use DateTime; /** * PHP Exif Exiftool Reader Adapter @@ -40,6 +39,11 @@ class Exiftool extends AdapterAbstract */ protected $numeric = true; + /** + * @var string + */ + protected $mapperClass = '\\PHPExif\\Mapper\\Exiftool'; + /** * Setter for the exiftool binary path * @@ -96,21 +100,25 @@ public function getToolPath() */ public function getExifFromFile($file) { - $gpsFormat = '%d deg %d\' %.4f\"'; - $result = $this->getCliOutput( sprintf( - '%1$s%3$s -j -c "%4$s" %2$s', + '%1$s%3$s -j %2$s', $this->getToolPath(), $file, - $this->numeric ? ' -n' : '', - $gpsFormat + $this->numeric ? ' -n' : '' ) ); $data = json_decode($result, true); - $mappedData = $this->mapData(reset($data)); - $exif = new Exif($mappedData); + + // map the data: + $mapper = $this->getMapper(); + $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; @@ -148,96 +156,5 @@ protected function getCliOutput($command) return $result; } - - /** - * Maps native data to Exif format - * - * @param array $source - * @return array - */ - public function mapData(array $source) - { - $focalLength = false; - if (isset($source['FocalLength'])) { - $focalLengthParts = explode(' ', $source['FocalLength']); - $focalLength = (int) reset($focalLengthParts); - } - - $exposureTime = false; - if (isset($source['ExposureTime'])) { - $exposureTime = '1/' . round(1 / $source['ExposureTime']); - } - - $caption = false; - if (isset($source['Caption'])) { - $caption = $source['Caption']; - } elseif (isset($source['Caption-Abstract'])) { - $caption = $source['Caption-Abstract']; - } - - $gpsLocation = false; - if (isset($source['GPSLatitudeRef']) && isset($source['GPSLongitudeRef'])) { - $latitude = $this->extractGPSCoordinates($source['GPSLatitude']); - $longitude = $this->extractGPSCoordinates($source['GPSLongitude']); - - if ($latitude !== false && $longitude !== false) { - $gpsLocation = sprintf( - '%s,%s', - (strtoupper($source['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $latitude, - (strtoupper($source['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $longitude - ); - } - } - - return array( - Exif::APERTURE => (!isset($source['Aperture'])) ? - false : sprintf('f/%01.1f', $source['Aperture']), - Exif::AUTHOR => (!isset($source['Artist'])) ? false : $source['Artist'], - Exif::CAMERA => (!isset($source['Model'])) ? false : $source['Model'], - Exif::CAPTION => $caption, - Exif::COLORSPACE => (!isset($source[Exif::COLORSPACE]) ? false : $source[Exif::COLORSPACE]), - Exif::COPYRIGHT => (!isset($source['Copyright'])) ? false : $source['Copyright'], - Exif::CREATION_DATE => (!isset($source['CreateDate'])) ? - false : DateTime::createFromFormat('Y:m:d H:i:s', $source['CreateDate']), - Exif::CREDIT => (!isset($source['Credit'])) ? false : $source['Credit'], - Exif::EXPOSURE => $exposureTime, - Exif::FILESIZE => (!isset($source[Exif::FILESIZE]) ? false : $source[Exif::FILESIZE]), - Exif::FOCAL_LENGTH => $focalLength, - Exif::FOCAL_DISTANCE => (!isset($source['ApproximateFocusDistance'])) ? - false : sprintf('%1$sm', $source['ApproximateFocusDistance']), - Exif::HEADLINE => (!isset($source['Headline'])) ? false : $source['Headline'], - Exif::HEIGHT => (!isset($source['ImageHeight'])) ? false : $source['ImageHeight'], - Exif::HORIZONTAL_RESOLUTION => (!isset($source['XResolution'])) ? false : $source['XResolution'], - Exif::ISO => (!isset($source['ISO'])) ? false : $source['ISO'], - Exif::JOB_TITLE => (!isset($source['JobTitle'])) ? false : $source['JobTitle'], - Exif::KEYWORDS => (!isset($source['Keywords'])) ? false : $source['Keywords'], - Exif::MIMETYPE => (!isset($source['MIMEType'])) ? false : $source['MIMEType'], - Exif::ORIENTATION => (!isset($source['Orientation'])) ? false : $source['Orientation'], - Exif::SOFTWARE => (!isset($source['Software'])) ? false : $source['Software'], - Exif::SOURCE => (!isset($source['Source'])) ? false : $source['Source'], - Exif::TITLE => (!isset($source['Title'])) ? false : $source['Title'], - Exif::VERTICAL_RESOLUTION => (!isset($source['YResolution'])) ? false : $source['YResolution'], - Exif::WIDTH => (!isset($source['ImageWidth'])) ? false : $source['ImageWidth'], - Exif::GPS => $gpsLocation, - ); - } - - /** - * 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/tests/PHPExif/Adapter/ExiftoolTest.php b/tests/PHPExif/Adapter/ExiftoolTest.php index 5e8783b..5d2b95c 100644 --- a/tests/PHPExif/Adapter/ExiftoolTest.php +++ b/tests/PHPExif/Adapter/ExiftoolTest.php @@ -73,103 +73,6 @@ public function testGetExifFromFile() $this->assertNotEmpty($result->getRawData()); } - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::mapData - */ - public function testMapDataReturnsArray() - { - $this->assertInternalType('array', $this->adapter->mapData(array())); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::mapData - */ - public function testMapDataReturnsArrayFalseValuesIfUndefined() - { - $result = $this->adapter->mapData(array()); - - foreach ($result as $value) { - $this->assertFalse($value); - } - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::mapData - */ - public function testMapDataResultHasAllKeys() - { - $reflClass = new \ReflectionClass('\PHPExif\Exif'); - $constants = $reflClass->getConstants(); - $result = $this->adapter->mapData(array()); - $keys = array_keys($result); - - $diff = array_diff($constants, $keys); - - $this->assertEquals(0, count($diff)); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::mapData - */ - public function testMapDataFocalLengthIsCalculated() - { - $focalLength = '18 mm.'; - - $result = $this->adapter->mapData( - array( - 'FocalLength' => $focalLength, - ) - ); - - $this->assertEquals(18, $result[\PHPExif\Exif::FOCAL_LENGTH]); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::setNumeric - * @covers \PHPExif\Adapter\Exiftool::mapData - * @covers \PHPExif\Adapter\Exiftool::extractGPSCoordinates - */ - public function testMapDataCreationDegGPSIsCalculated() - { - $this->adapter->setNumeric(false); - $result = $this->adapter->mapData( - array( - 'GPSLatitude' => '40 deg 20\' 0.42857" N', - 'GPSLatitudeRef' => 'North', - 'GPSLongitude' => '20 deg 10\' 2.33333" W', - 'GPSLongitudeRef' => 'West', - ) - ); - - $expected = '40.333452380556,-20.167314813889'; - $this->assertEquals($expected, $result[\PHPExif\Exif::GPS]); - } - - /** - * @group exiftool - * @covers \PHPExif\Adapter\Exiftool::mapData - * @covers \PHPExif\Adapter\Exiftool::extractGPSCoordinates - */ - public function testMapDataCreationNumericGPSIsCalculated() - { - $result = $this->adapter->mapData( - array( - 'GPSLatitude' => '40.333452381', - 'GPSLatitudeRef' => 'North', - 'GPSLongitude' => '20.167314814', - 'GPSLongitudeRef' => 'West', - ) - ); - - $expected = '40.333452381,-20.167314814'; - $this->assertEquals($expected, $result[\PHPExif\Exif::GPS]); - } - /** * @group exiftool * @covers \PHPExif\Adapter\Exiftool::getCliOutput From ae92380b78c452e8f706e085e34a213bc8aa7742 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 19:29:27 +0200 Subject: [PATCH 05/37] Extracted mapping of native data to separate mapper & updatd Native adapter to use that mapper Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/Native.php | 179 +++------------------------ tests/PHPExif/Adapter/NativeTest.php | 161 ------------------------ 2 files changed, 16 insertions(+), 324 deletions(-) diff --git a/lib/PHPExif/Adapter/Native.php b/lib/PHPExif/Adapter/Native.php index a7d6756..80fa630 100644 --- a/lib/PHPExif/Adapter/Native.php +++ b/lib/PHPExif/Adapter/Native.php @@ -60,6 +60,11 @@ class Native extends AdapterAbstract */ protected $sectionsAsArrays = self::SECTIONS_FLAT; + /** + * @var string + */ + protected $mapperClass = '\\PHPExif\\Mapper\\Native'; + /** * Contains the mapping of names to IPTC field numbers * @@ -189,8 +194,15 @@ public function getExifFromFile($file) $xmpData = $this->getIptcData($file); $data = array_merge($data, array(self::SECTION_IPTC => $xmpData)); - $mappedData = $this->mapData($data); - $exif = new Exif($mappedData); + + // 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; @@ -204,7 +216,7 @@ public function getExifFromFile($file) */ public function getIptcData($file) { - getimagesize($file, $info); + $size = getimagesize($file, $info); $arrData = array(); if (isset($info['APP13'])) { $iptc = iptcparse($info['APP13']); @@ -224,164 +236,5 @@ public function getIptcData($file) return $arrData; } - - /** - * Maps native data to Exif format - * - * @param array $source - * @return array - */ - public function mapData(array $source) - { - $focalLength = false; - if (isset($source['FocalLength'])) { - $parts = explode('/', $source['FocalLength']); - $focalLength = (int)reset($parts) / (int)end($parts); - } - - $horResolution = false; - if (isset($source['XResolution'])) { - $resolutionParts = explode('/', $source['XResolution']); - $horResolution = (int)reset($resolutionParts); - } - - $vertResolution = false; - if (isset($source['YResolution'])) { - $resolutionParts = explode('/', $source['YResolution']); - $vertResolution = (int)reset($resolutionParts); - } - - $exposureTime = false; - if (isset($source['ExposureTime'])) { - // normalize ExposureTime - // on one test image, it reported "10/300" instead of "1/30" - list($counter, $denominator) = explode('/', $source['ExposureTime']); - if (intval($counter) !== 1) { - $denominator /= $counter; - } - $exposureTime = '1/' . round($denominator); - } - - $gpsLocation = false; - if (isset($source['GPSLatitudeRef']) && isset($source['GPSLongitudeRef'])) { - $latitude = $this->extractGPSCoordinate($source['GPSLatitude']); - $longitude = $this->extractGPSCoordinate($source['GPSLongitude']); - - $gpsLocation = sprintf( - '%s,%s', - (strtoupper($source['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $latitude, - (strtoupper($source['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $longitude - ); - } - - return array( - Exif::APERTURE => (!isset($source[self::SECTION_COMPUTED]['ApertureFNumber'])) ? - false : $source[self::SECTION_COMPUTED]['ApertureFNumber'], - Exif::AUTHOR => (!isset($source['Artist'])) ? false : $source['Artist'], - Exif::CAMERA => (!isset($source['Model'])) ? false : $source['Model'], - Exif::CAPTION => (!isset($source[self::SECTION_IPTC]['caption'])) ? - false : $source[self::SECTION_IPTC]['caption'], - Exif::COLORSPACE => (!isset($source[Exif::COLORSPACE]) ? false : $source[Exif::COLORSPACE]), - Exif::COPYRIGHT => (!isset($source[self::SECTION_IPTC]['copyright'])) ? - false : $source[self::SECTION_IPTC]['copyright'], - Exif::CREATION_DATE => (!isset($source['DateTimeOriginal'])) ? - false : DateTime::createFromFormat('Y:m:d H:i:s', $source['DateTimeOriginal']), - Exif::CREDIT => (!isset($source[self::SECTION_IPTC]['credit'])) ? - false : $source[self::SECTION_IPTC]['credit'], - Exif::EXPOSURE => $exposureTime, - Exif::FILESIZE => (!isset($source[Exif::FILESIZE]) ? false : $source[Exif::FILESIZE]), - Exif::FOCAL_LENGTH => $focalLength, - Exif::FOCAL_DISTANCE => (!isset($source[self::SECTION_COMPUTED]['FocusDistance'])) ? - false : $source[self::SECTION_COMPUTED]['FocusDistance'], - Exif::HEADLINE => (!isset($source[self::SECTION_IPTC]['headline'])) ? - false : $source[self::SECTION_IPTC]['headline'], - Exif::HEIGHT => (!isset($source[self::SECTION_COMPUTED]['Height'])) ? - false : $source[self::SECTION_COMPUTED]['Height'], - Exif::HORIZONTAL_RESOLUTION => $horResolution, - Exif::ISO => (!isset($source['ISOSpeedRatings'])) ? false : $source['ISOSpeedRatings'], - Exif::JOB_TITLE => (!isset($source[self::SECTION_IPTC]['jobtitle'])) ? - false : $source[self::SECTION_IPTC]['jobtitle'], - Exif::KEYWORDS => (!isset($source[self::SECTION_IPTC]['keywords'])) ? - false : $source[self::SECTION_IPTC]['keywords'], - Exif::MIMETYPE => (!isset($source[Exif::MIMETYPE]) ? false : $source[Exif::MIMETYPE]), - Exif::ORIENTATION => (!isset($source[Exif::ORIENTATION]) ? false : $source[Exif::ORIENTATION]), - Exif::SOFTWARE => (!isset($source['Software'])) ? false : trim($source['Software']), - Exif::SOURCE => (!isset($source[self::SECTION_IPTC]['source'])) ? - false : $source[self::SECTION_IPTC]['source'], - Exif::TITLE => (!isset($source[self::SECTION_IPTC]['title'])) ? - false : $source[self::SECTION_IPTC]['title'], - Exif::VERTICAL_RESOLUTION => $vertResolution, - Exif::WIDTH => (!isset($source[self::SECTION_COMPUTED]['Width'])) ? - false : $source[self::SECTION_COMPUTED]['Width'], - Exif::GPS => $gpsLocation, - ); - - $arrMapping = array( - array( - Exif::AUTHOR => 'Artist', - Exif::CAMERA => 'Model', - Exif::EXPOSURE => 'ExposureTime', - Exif::ISO => 'ISOSpeedRatings', - Exif::SOFTWARE => 'Software', - ), - self::SECTION_COMPUTED => array( - Exif::APERTURE => 'ApertureFNumber', - Exif::FOCAL_DISTANCE => 'FocusDistance', - Exif::HEIGHT => 'Height', - Exif::WIDTH => 'Width', - ), - self::SECTION_IPTC => array( - Exif::CAPTION => 'caption', - Exif::COPYRIGHT => 'copyright', - Exif::CREDIT => 'credit', - Exif::HEADLINE => 'headline', - Exif::JOB_TITLE => 'jobtitle', - Exif::KEYWORDS => 'keywords', - Exif::SOURCE => 'source', - Exif::TITLE => 'title', - ), - ); - - foreach ($arrMapping as $key => $arrFields) { - if (array_key_exists($key, $source)) { - $arrSource = $source[$key]; - } else { - $arrSource = $source; - } - - foreach ($arrFields as $mappedField => $field) { - if (isset($arrSource[$field])) { - $mappedData[$mappedField] = $arrSource[$field]; - } - } - } - - return $mappedData; - } - - /** - * Extract GPS coordinates from components array - * - * @param array $components - * @return float - */ - protected function extractGPSCoordinate(array $components) - { - $components = array_map(array($this, 'normalizeGPSComponent'), $components); - - return intval($components[0]) + (intval($components[1]) / 60) + (floatval($components[2]) / 3600); - } - - /** - * Normalize GPS coordinates components - * - * @param mixed $component - * @return int|float - */ - protected function normalizeGPSComponent($component) - { - $parts = explode('/', $component); - - return count($parts) === 1 ? $parts[0] : (int) reset($parts) / (int) end($parts); - } } + diff --git a/tests/PHPExif/Adapter/NativeTest.php b/tests/PHPExif/Adapter/NativeTest.php index 381f506..4675b3a 100755 --- a/tests/PHPExif/Adapter/NativeTest.php +++ b/tests/PHPExif/Adapter/NativeTest.php @@ -179,165 +179,4 @@ public function testGetSectionsAsArrayFromProperty() $this->assertEquals(\PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS, $this->adapter->getSectionsAsArrays()); } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataReturnsArray() - { - $this->assertInternalType('array', $this->adapter->mapData(array())); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataMapsFirstLevel() - { - $result = $this->adapter->mapData( - array( - 'Software' => 'Foo', - ) - ); - $this->assertEquals( - 'Foo', - $result[\PHPExif\Exif::SOFTWARE] - ); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataMapsSecondLevel() - { - $result = $this->adapter->mapData( - array( - \PHPExif\Adapter\Native::SECTION_COMPUTED => array( - 'Height' => '1500' - ) - ) - ); - $this->assertEquals( - 1500, - $result[\PHPExif\Exif::HEIGHT] - ); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataReturnsArrayFalseValuesIfUndefined() - { - $result = $this->adapter->mapData(array()); - - foreach ($result as $key => $value) { - $this->assertFalse($value); - } - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataResultHasAllKeys() - { - $reflClass = new \ReflectionClass('\PHPExif\Exif'); - $constants = $reflClass->getConstants(); - $result = $this->adapter->mapData(array()); - $keys = array_keys($result); - - $diff = array_diff($constants, $keys); - - $this->assertEquals(0, count($diff)); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataFocalLengthIsCalculated() - { - $focalLength = '1/320'; - - $result = $this->adapter->mapData( - array( - 'FocalLength' => $focalLength, - ) - ); - - $this->assertEquals(1/320, $result[\PHPExif\Exif::FOCAL_LENGTH]); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataHorizontalResolutionIsCalculated() - { - $xRes = '240/1'; - - $result = $this->adapter->mapData( - array( - 'XResolution' => $xRes, - ) - ); - - $this->assertEquals(240, $result[\PHPExif\Exif::HORIZONTAL_RESOLUTION]); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataVerticalResolutionIsCalculated() - { - $yRes = '240/1'; - - $result = $this->adapter->mapData( - array( - 'YResolution' => $yRes, - ) - ); - - $this->assertEquals(240, $result[\PHPExif\Exif::VERTICAL_RESOLUTION]); - } - - /** - * @group native-curr - * @covers \PHPExif\Adapter\Native::mapData - */ - public function testMapDataCreationDateIsConvertedToDatetime() - { - $result = $this->adapter->mapData( - array( - 'DateTimeOriginal' => '2013:06:30 12:34:56', - ) - ); - - $this->assertInstanceOf('DateTime', $result[\PHPExif\Exif::CREATION_DATE]); - } - - /** - * @group native - * @covers \PHPExif\Adapter\Native::mapData - * @covers \PHPExif\Adapter\Native::extractGPSCoordinate - * @covers \PHPExif\Adapter\Native::normalizeGPSComponent - */ - public function testMapDataCreationGPSIsCalculated() - { - $result = $this->adapter->mapData( - array( - 'GPSLatitude' => array('40/1', '20/1', '15/35'), - 'GPSLatitudeRef' => 'N', - 'GPSLongitude' => array('20/1', '10/1', '35/15'), - 'GPSLongitudeRef' => 'W', - ) - ); - - $expected = '40.333452380952,-20.167314814815'; - $this->assertEquals($expected, $result[\PHPExif\Exif::GPS]); - } } From 0ba62768f73dfbea36276b696b036d407b345b64 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 21:52:22 +0200 Subject: [PATCH 06/37] Bugfixed some small inconsistencies Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Mapper/Exiftool.php | 6 +++--- lib/PHPExif/Mapper/Native.php | 31 +++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php index 27dbbe2..5c21466 100644 --- a/lib/PHPExif/Mapper/Exiftool.php +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -31,7 +31,7 @@ class Exiftool implements MapperInterface const CAPTIONABSTRACT = 'Caption-Abstract'; const COLORSPACE = 'ColorSpace'; const COPYRIGHT = 'Copyright'; - const CREATIONDATE = 'CreationDate'; + const CREATEDATE = 'CreateDate'; const CREDIT = 'Credit'; const EXPOSURETIME = 'ExposureTime'; const FILESIZE = 'FileSize'; @@ -65,7 +65,7 @@ class Exiftool implements MapperInterface self::CAPTIONABSTRACT => Exif::CAPTION, self::COLORSPACE => Exif::COLORSPACE, self::COPYRIGHT => Exif::COPYRIGHT, - self::CREATIONDATE => Exif::CREATION_DATE, + self::CREATEDATE => Exif::CREATION_DATE, self::CREDIT => Exif::CREDIT, self::EXPOSURETIME => Exif::EXPOSURE, self::FILESIZE => Exif::FILESIZE, @@ -112,7 +112,7 @@ public function mapRawData(array $data) case self::APPROXIMATEFOCUSDISTANCE: $value = sprintf('%1$sm', $value); break; - case self::CREATIONDATE: + case self::CREATEDATE: $value = DateTime::createFromFormat('Y:m:d H:i:s', $value); break; case self::EXPOSURETIME: diff --git a/lib/PHPExif/Mapper/Native.php b/lib/PHPExif/Mapper/Native.php index ac36580..b8502cb 100644 --- a/lib/PHPExif/Mapper/Native.php +++ b/lib/PHPExif/Mapper/Native.php @@ -40,7 +40,7 @@ class Native implements MapperInterface const ISOSPEEDRATINGS = 'ISOSpeedRatings'; const JOBTITLE = 'jobtitle'; const KEYWORDS = 'keywords'; - const MIMETYPE = 'MIMEType'; + const MIMETYPE = 'MimeType'; const MODEL = 'Model'; const ORIENTATION = 'Orientation'; const SOFTWARE = 'Software'; @@ -59,6 +59,22 @@ class Native implements MapperInterface 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 @@ -108,7 +124,7 @@ public function mapRawData(array $data) { $mappedData = array(); foreach ($data as $field => $value) { - if (is_string($field) && is_array($value)) { + if ($this->isSection($field) && is_array($value)) { $subData = $this->mapRawData($value); $mappedData = array_merge($mappedData, $subData); @@ -153,5 +169,16 @@ public function mapRawData(array $data) return $mappedData; } + + /** + * Determines if given field is a section + * + * @param string $field + * @return bool + */ + protected function isSection($field) + { + return (in_array($field, $this->sections)); + } } From fb7763f5f478e0a1d66f975b1ceb929f33cd2189 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 21:52:37 +0200 Subject: [PATCH 07/37] Added mutators to Exif class & updated unit tests Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Exif.php | 339 +++++++++++++++++++++++++++++++++++-- tests/PHPExif/ExifTest.php | 4 +- 2 files changed, 328 insertions(+), 15 deletions(-) diff --git a/lib/PHPExif/Exif.php b/lib/PHPExif/Exif.php index 4f39c6d..8eddff5 100755 --- a/lib/PHPExif/Exif.php +++ b/lib/PHPExif/Exif.php @@ -47,7 +47,6 @@ class Exif const TITLE = 'title'; const VERTICAL_RESOLUTION = 'verticalResolution'; const WIDTH = 'width'; - const GPS = 'gps'; /** * The mapped EXIF data @@ -133,6 +132,19 @@ public function getAperture() 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 * @@ -147,6 +159,19 @@ public function getAuthor() 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 * @@ -161,6 +186,19 @@ public function getHeadline() 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 * @@ -175,6 +213,19 @@ public function getCredit() 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 * @@ -189,6 +240,19 @@ public function getSource() 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 * @@ -203,6 +267,19 @@ public function getJobtitle() 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 * @@ -217,6 +294,19 @@ public function getIso() 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 * @@ -231,6 +321,19 @@ public function getExposure() 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 * @@ -261,6 +364,19 @@ public function getFocusDistance() 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 * @@ -275,6 +391,19 @@ public function getWidth() 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 * @@ -289,6 +418,19 @@ public function getHeight() 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 * @@ -303,6 +445,19 @@ public function getTitle() 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 * @@ -317,6 +472,19 @@ public function getCaption() 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 * @@ -331,6 +499,19 @@ public function getCopyright() 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 * @@ -345,6 +526,19 @@ public function getKeywords() 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 * @@ -359,6 +553,19 @@ public function getCamera() 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 * @@ -373,6 +580,19 @@ public function getHorizontalResolution() 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 * @@ -387,6 +607,19 @@ public function getVerticalResolution() 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 * @@ -401,6 +634,19 @@ public function getSoftware() 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 * @@ -415,6 +661,19 @@ public function getFocalLength() 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 * @@ -429,6 +688,19 @@ public function getCreationDate() 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 * @@ -439,10 +711,23 @@ 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 * @@ -453,28 +738,54 @@ public function getMimeType() if (!isset($this->data[self::MIMETYPE])) { return false; } - + return $this->data[self::MIMETYPE]; } /** - * Returns the filesize, if it exists + * Sets the mimetype * - * @return integer + * @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 */ 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 integer + * @return int */ public function getOrientation() { @@ -486,16 +797,16 @@ public function getOrientation() } /** - * Returns GPS coordinates, if it exists + * Sets the orientation * - * @return array|boolean + * @param int $value + * @return \PHPExif\Exif */ - public function getGPS() + public function setOrientation($value) { - if (!isset($this->data[self::GPS])) { - return false; - } + $this->data[self::ORIENTATION] = $value; - return $this->data[self::GPS]; + return $this; } } + diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index 8f51f21..e5fc29a 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -460,6 +460,8 @@ public function testGetGPS() /** * Test that the values returned by both adapters are equal + * + * @group consistency */ public function testAdapterConsistency() { @@ -480,7 +482,7 @@ public function testAdapterConsistency() // 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') { + if (strpos($name, 'get') !== 0 || $name == 'getRawData' || $name == 'getData') { continue; } $this->assertEquals( From ec812d9e1ff4a1c4e9116be457fc3466f6dcd0da Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Sun, 29 Mar 2015 21:57:50 +0200 Subject: [PATCH 08/37] Removed blank lines to conform to PSR2 Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/Exiftool.php | 1 - lib/PHPExif/Adapter/Native.php | 1 - lib/PHPExif/Exif.php | 1 - lib/PHPExif/Hydrator/HydratorInterface.php | 1 - lib/PHPExif/Hydrator/Mutator.php | 1 - lib/PHPExif/Mapper/Exiftool.php | 1 - lib/PHPExif/Mapper/MapperInterface.php | 1 - lib/PHPExif/Mapper/Native.php | 1 - 8 files changed, 8 deletions(-) diff --git a/lib/PHPExif/Adapter/Exiftool.php b/lib/PHPExif/Adapter/Exiftool.php index f7169ac..d8f715b 100644 --- a/lib/PHPExif/Adapter/Exiftool.php +++ b/lib/PHPExif/Adapter/Exiftool.php @@ -157,4 +157,3 @@ protected function getCliOutput($command) return $result; } } - diff --git a/lib/PHPExif/Adapter/Native.php b/lib/PHPExif/Adapter/Native.php index 80fa630..862aa5a 100644 --- a/lib/PHPExif/Adapter/Native.php +++ b/lib/PHPExif/Adapter/Native.php @@ -237,4 +237,3 @@ public function getIptcData($file) return $arrData; } } - diff --git a/lib/PHPExif/Exif.php b/lib/PHPExif/Exif.php index 8eddff5..bbf1bea 100755 --- a/lib/PHPExif/Exif.php +++ b/lib/PHPExif/Exif.php @@ -809,4 +809,3 @@ public function setOrientation($value) return $this; } } - diff --git a/lib/PHPExif/Hydrator/HydratorInterface.php b/lib/PHPExif/Hydrator/HydratorInterface.php index 8f81bdd..fd8b797 100644 --- a/lib/PHPExif/Hydrator/HydratorInterface.php +++ b/lib/PHPExif/Hydrator/HydratorInterface.php @@ -30,4 +30,3 @@ interface HydratorInterface */ public function hydrate($object, array $data); } - diff --git a/lib/PHPExif/Hydrator/Mutator.php b/lib/PHPExif/Hydrator/Mutator.php index 52559d1..164d57c 100644 --- a/lib/PHPExif/Hydrator/Mutator.php +++ b/lib/PHPExif/Hydrator/Mutator.php @@ -53,4 +53,3 @@ protected function determineMutator($property) return $method; } } - diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php index 5c21466..3baa68a 100644 --- a/lib/PHPExif/Mapper/Exiftool.php +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -131,4 +131,3 @@ public function mapRawData(array $data) return $mappedData; } } - diff --git a/lib/PHPExif/Mapper/MapperInterface.php b/lib/PHPExif/Mapper/MapperInterface.php index 234ca06..0479740 100644 --- a/lib/PHPExif/Mapper/MapperInterface.php +++ b/lib/PHPExif/Mapper/MapperInterface.php @@ -30,4 +30,3 @@ interface MapperInterface */ public function mapRawData(array $data); } - diff --git a/lib/PHPExif/Mapper/Native.php b/lib/PHPExif/Mapper/Native.php index b8502cb..689c983 100644 --- a/lib/PHPExif/Mapper/Native.php +++ b/lib/PHPExif/Mapper/Native.php @@ -181,4 +181,3 @@ protected function isSection($field) return (in_array($field, $this->sections)); } } - From 3c36d12ebb8dd2b412c7f0f869fa0a7113d33cdc Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 30 Mar 2015 13:35:22 +0200 Subject: [PATCH 09/37] Add unit test for Exiftool::setNumeric Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Adapter/ExiftoolTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/PHPExif/Adapter/ExiftoolTest.php b/tests/PHPExif/Adapter/ExiftoolTest.php index 5d2b95c..7211f37 100644 --- a/tests/PHPExif/Adapter/ExiftoolTest.php +++ b/tests/PHPExif/Adapter/ExiftoolTest.php @@ -60,6 +60,21 @@ 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 From 2daf6e169bd3b8bfa9f1562cc6e9f3ed877ecd7d Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 30 Mar 2015 13:47:59 +0200 Subject: [PATCH 10/37] Add extra unit tests for Reader class Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Reader/ReaderTest.php | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/PHPExif/Reader/ReaderTest.php b/tests/PHPExif/Reader/ReaderTest.php index af546c4..4d62602 100644 --- a/tests/PHPExif/Reader/ReaderTest.php +++ b/tests/PHPExif/Reader/ReaderTest.php @@ -45,6 +45,20 @@ public function testGetAdapterFromProperty() $this->assertSame($mock, $this->reader->getAdapter()); } + /** + * @group reader + * @covers \PHPExif\Reader\Reader::getAdapter + * @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 @@ -112,4 +126,30 @@ public function testFactoryAdapterTypeExiftool() $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); + } } + From a288667ae656b27674d9fb2163631c47af2b95ea Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 30 Mar 2015 14:56:09 +0200 Subject: [PATCH 11/37] Add some tests for Exif class Signed-off-by: Tom Van Herreweghe --- .travis.yml | 2 +- tests/PHPExif/ExifTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6272df..90c6091 100755 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ matrix: script: - mkdir -p build/logs - php vendor/bin/phpunit -c phpunit.xml.dist - - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml + - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml --strict-coverage - ./vendor/bin/phpcs --standard=PSR2 ./lib/ before_script: diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index e5fc29a..51de23f 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -133,6 +133,8 @@ public function providerUndefinedPropertiesReturnFalse() array('getCredit'), array('getSource'), array('getJobtitle'), + array('getMimeType'), + array('getFileSize'), ); } @@ -494,3 +496,4 @@ public function testAdapterConsistency() } } } + From d16cacb469eae0e48d58437da1717f55172ae60a Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 30 Mar 2015 15:01:45 +0200 Subject: [PATCH 12/37] Remove strict coverage option Signed-off-by: Tom Van Herreweghe --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 90c6091..b6272df 100755 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ matrix: script: - mkdir -p build/logs - php vendor/bin/phpunit -c phpunit.xml.dist - - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml --strict-coverage + - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml - ./vendor/bin/phpcs --standard=PSR2 ./lib/ before_script: From 4e0ee69d491d35ce20ef29899b4ab9334431cf98 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 30 Mar 2015 15:44:24 +0200 Subject: [PATCH 13/37] Made coverage more explicit Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Adapter/AdapterAbstractTest.php | 4 +++- tests/PHPExif/Adapter/ExiftoolTest.php | 3 +++ tests/PHPExif/Adapter/NativeTest.php | 3 +++ tests/PHPExif/ExifTest.php | 4 +++- tests/PHPExif/Reader/ReaderTest.php | 3 +++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/PHPExif/Adapter/AdapterAbstractTest.php b/tests/PHPExif/Adapter/AdapterAbstractTest.php index fd52e37..7b30d48 100644 --- a/tests/PHPExif/Adapter/AdapterAbstractTest.php +++ b/tests/PHPExif/Adapter/AdapterAbstractTest.php @@ -1,5 +1,7 @@ + */ class AdapterAbstractTest extends \PHPUnit_Framework_TestCase { /** diff --git a/tests/PHPExif/Adapter/ExiftoolTest.php b/tests/PHPExif/Adapter/ExiftoolTest.php index 7211f37..71abd2a 100644 --- a/tests/PHPExif/Adapter/ExiftoolTest.php +++ b/tests/PHPExif/Adapter/ExiftoolTest.php @@ -1,4 +1,7 @@ + */ class ExiftoolTest extends \PHPUnit_Framework_TestCase { /** diff --git a/tests/PHPExif/Adapter/NativeTest.php b/tests/PHPExif/Adapter/NativeTest.php index 4675b3a..7dd86b6 100755 --- a/tests/PHPExif/Adapter/NativeTest.php +++ b/tests/PHPExif/Adapter/NativeTest.php @@ -1,4 +1,7 @@ + */ class NativeTest extends \PHPUnit_Framework_TestCase { /** diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index 51de23f..bfee7f5 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -1,5 +1,7 @@ + */ class ExifTest extends \PHPUnit_Framework_TestCase { /** diff --git a/tests/PHPExif/Reader/ReaderTest.php b/tests/PHPExif/Reader/ReaderTest.php index 4d62602..7e8c0c0 100644 --- a/tests/PHPExif/Reader/ReaderTest.php +++ b/tests/PHPExif/Reader/ReaderTest.php @@ -1,4 +1,7 @@ + */ class ReaderTest extends \PHPUnit_Framework_TestCase { /** From 5eb8ca59b0689837e7dfe1fedb4ce0a8e32a163e Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 30 Mar 2015 16:22:04 +0200 Subject: [PATCH 14/37] Add @covers annotation for Exif tests Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/ExifTest.php | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index bfee7f5..7e8d420 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -19,6 +19,7 @@ public function setUp() /** * @group exif + * @covers \PHPExif\Exif::__construct */ public function testConstructorCallsSetData() { @@ -44,6 +45,7 @@ public function testConstructorCallsSetData() /** * @group exif + * @covers \PHPExif\Exif::getRawData */ public function testGetRawData() { @@ -55,6 +57,7 @@ public function testGetRawData() /** * @group exif + * @covers \PHPExif\Exif::setRawData */ public function testSetRawData() { @@ -70,6 +73,7 @@ public function testSetRawData() /** * @group exif + * @covers \PHPExif\Exif::getData */ public function testGetData() { @@ -81,6 +85,7 @@ public function testGetData() /** * @group exif + * @covers \PHPExif\Exif::setData */ public function testSetData() { @@ -97,6 +102,29 @@ public function testSetData() /** * * @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 * @param string $accessor */ public function testUndefinedPropertiesReturnFalse($accessor) @@ -442,6 +470,10 @@ public function testGetFileSize() $this->assertEquals($expected, $this->exif->getFileSize()); } + /** + * @group exif + * @covers \PHPExif\Exif::getOrientation + */ public function testGetOrientation() { $expected = 1; @@ -466,6 +498,29 @@ public function testGetGPS() * 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() { From cf21a3f2e30d678db70da249620ee529d5e345eb Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 1 Apr 2015 13:35:23 +0200 Subject: [PATCH 15/37] Add unit tests for Mutator class Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Hydrator/MutatorTest.php | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/PHPExif/Hydrator/MutatorTest.php diff --git a/tests/PHPExif/Hydrator/MutatorTest.php b/tests/PHPExif/Hydrator/MutatorTest.php new file mode 100644 index 0000000..e37e1d1 --- /dev/null +++ b/tests/PHPExif/Hydrator/MutatorTest.php @@ -0,0 +1,68 @@ + + */ +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() + { + } +} + From 2b7fbc6c9521cbe8d1a791a6f63afc4d39b8703f Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 1 Apr 2015 14:37:42 +0200 Subject: [PATCH 16/37] Add extra unit tests for AdapterAbstract Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Adapter/AdapterAbstractTest.php | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/tests/PHPExif/Adapter/AdapterAbstractTest.php b/tests/PHPExif/Adapter/AdapterAbstractTest.php index 7b30d48..a020bb3 100644 --- a/tests/PHPExif/Adapter/AdapterAbstractTest.php +++ b/tests/PHPExif/Adapter/AdapterAbstractTest.php @@ -82,4 +82,150 @@ public function testConstructorSetsOptions() $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)); + } } + From 281aebd4f371d5ea1394fb6b93f5fa59570b9a2c Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 1 Apr 2015 17:40:39 +0200 Subject: [PATCH 17/37] Add coverage for interfaces & exceptions Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Adapter/AdapterAbstractTest.php | 1 + tests/PHPExif/Hydrator/MutatorTest.php | 1 + tests/PHPExif/Reader/ReaderTest.php | 2 ++ 3 files changed, 4 insertions(+) diff --git a/tests/PHPExif/Adapter/AdapterAbstractTest.php b/tests/PHPExif/Adapter/AdapterAbstractTest.php index a020bb3..2cae725 100644 --- a/tests/PHPExif/Adapter/AdapterAbstractTest.php +++ b/tests/PHPExif/Adapter/AdapterAbstractTest.php @@ -1,6 +1,7 @@ + * @covers \PHPExif\Adapter\AdapterInterface:: */ class AdapterAbstractTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/PHPExif/Hydrator/MutatorTest.php b/tests/PHPExif/Hydrator/MutatorTest.php index e37e1d1..8bb57e0 100644 --- a/tests/PHPExif/Hydrator/MutatorTest.php +++ b/tests/PHPExif/Hydrator/MutatorTest.php @@ -1,6 +1,7 @@ + * @covers \PHPExif\Hydrator\HydratorInterface:: */ class MutatorTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/PHPExif/Reader/ReaderTest.php b/tests/PHPExif/Reader/ReaderTest.php index 7e8c0c0..a615271 100644 --- a/tests/PHPExif/Reader/ReaderTest.php +++ b/tests/PHPExif/Reader/ReaderTest.php @@ -1,6 +1,8 @@ + * @covers \PHPExif\Reader\ReaderInterface:: + * @covers \PHPExif\Adapter\NoAdapterException:: */ class ReaderTest extends \PHPUnit_Framework_TestCase { From 8214151b8d5acf2160924baf4ca25b3db1e150ed Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 1 Apr 2015 17:51:37 +0200 Subject: [PATCH 18/37] Beter interface coverage? Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Adapter/AdapterAbstractTest.php | 2 +- tests/PHPExif/Hydrator/MutatorTest.php | 2 +- tests/PHPExif/Reader/ReaderTest.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/PHPExif/Adapter/AdapterAbstractTest.php b/tests/PHPExif/Adapter/AdapterAbstractTest.php index 2cae725..46982da 100644 --- a/tests/PHPExif/Adapter/AdapterAbstractTest.php +++ b/tests/PHPExif/Adapter/AdapterAbstractTest.php @@ -1,7 +1,7 @@ - * @covers \PHPExif\Adapter\AdapterInterface:: + * @covers \PHPExif\Adapter\AdapterInterface */ class AdapterAbstractTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/PHPExif/Hydrator/MutatorTest.php b/tests/PHPExif/Hydrator/MutatorTest.php index 8bb57e0..280188b 100644 --- a/tests/PHPExif/Hydrator/MutatorTest.php +++ b/tests/PHPExif/Hydrator/MutatorTest.php @@ -1,7 +1,7 @@ - * @covers \PHPExif\Hydrator\HydratorInterface:: + * @covers \PHPExif\Hydrator\HydratorInterface */ class MutatorTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/PHPExif/Reader/ReaderTest.php b/tests/PHPExif/Reader/ReaderTest.php index a615271..f3fa22b 100644 --- a/tests/PHPExif/Reader/ReaderTest.php +++ b/tests/PHPExif/Reader/ReaderTest.php @@ -1,8 +1,8 @@ - * @covers \PHPExif\Reader\ReaderInterface:: - * @covers \PHPExif\Adapter\NoAdapterException:: + * @covers \PHPExif\Reader\ReaderInterface + * @covers \PHPExif\Adapter\NoAdapterException */ class ReaderTest extends \PHPUnit_Framework_TestCase { From f4eaad8640ab4da9e9437d67cc934e45d638dde8 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Wed, 1 Apr 2015 18:03:14 +0200 Subject: [PATCH 19/37] Add coverage ignore tags Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/AdapterInterface.php | 1 + lib/PHPExif/Adapter/NoAdapterException.php | 1 + lib/PHPExif/Hydrator/HydratorInterface.php | 1 + lib/PHPExif/Mapper/MapperInterface.php | 1 + lib/PHPExif/Reader/ReaderInterface.php | 19 +++++++++++++++++++ 5 files changed, 23 insertions(+) diff --git a/lib/PHPExif/Adapter/AdapterInterface.php b/lib/PHPExif/Adapter/AdapterInterface.php index fc44802..780e77d 100644 --- a/lib/PHPExif/Adapter/AdapterInterface.php +++ b/lib/PHPExif/Adapter/AdapterInterface.php @@ -7,6 +7,7 @@ * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif * @package Reader + * @codeCoverageIgnore */ namespace PHPExif\Adapter; diff --git a/lib/PHPExif/Adapter/NoAdapterException.php b/lib/PHPExif/Adapter/NoAdapterException.php index 6d56104..8a2b011 100644 --- a/lib/PHPExif/Adapter/NoAdapterException.php +++ b/lib/PHPExif/Adapter/NoAdapterException.php @@ -7,6 +7,7 @@ * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif * @package Reader + * @codeCoverageIgnore */ namespace PHPExif\Adapter; diff --git a/lib/PHPExif/Hydrator/HydratorInterface.php b/lib/PHPExif/Hydrator/HydratorInterface.php index fd8b797..d884327 100644 --- a/lib/PHPExif/Hydrator/HydratorInterface.php +++ b/lib/PHPExif/Hydrator/HydratorInterface.php @@ -7,6 +7,7 @@ * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif * @package Hydrator + * @codeCoverageIgnore */ namespace PHPExif\Hydrator; diff --git a/lib/PHPExif/Mapper/MapperInterface.php b/lib/PHPExif/Mapper/MapperInterface.php index 0479740..89a20e0 100644 --- a/lib/PHPExif/Mapper/MapperInterface.php +++ b/lib/PHPExif/Mapper/MapperInterface.php @@ -7,6 +7,7 @@ * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License * @category PHPExif * @package Mapper + * @codeCoverageIgnore */ namespace PHPExif\Mapper; diff --git a/lib/PHPExif/Reader/ReaderInterface.php b/lib/PHPExif/Reader/ReaderInterface.php index 76423e2..9617396 100644 --- a/lib/PHPExif/Reader/ReaderInterface.php +++ b/lib/PHPExif/Reader/ReaderInterface.php @@ -1,7 +1,26 @@ + * @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 { /** From 836ac7c4a55aa476cc7f9e730d2886467ab447b7 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 10:09:36 +0200 Subject: [PATCH 20/37] Add unit test for Exif mutators Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Exif.php | 8 +++--- tests/PHPExif/ExifTest.php | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/lib/PHPExif/Exif.php b/lib/PHPExif/Exif.php index bbf1bea..f9c2b2f 100755 --- a/lib/PHPExif/Exif.php +++ b/lib/PHPExif/Exif.php @@ -704,7 +704,7 @@ public function setCreationDate(\DateTime $value) /** * Returns the colorspace, if it exists * - * @return string + * @return string|boolean */ public function getColorSpace() { @@ -731,7 +731,7 @@ public function setColorSpace($value) /** * Returns the mimetype, if it exists * - * @return string + * @return string|boolean */ public function getMimeType() { @@ -758,7 +758,7 @@ public function setMimeType($value) /** * Returns the filesize, if it exists * - * @return int + * @return int|boolean */ public function getFileSize() { @@ -785,7 +785,7 @@ public function setFileSize($value) /** * Returns the orientation, if it exists * - * @return int + * @return int|boolean */ public function getOrientation() { diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index 7e8d420..8009eee 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -494,6 +494,62 @@ public function testGetGPS() $this->assertEquals($expected, $this->exif->getGPS()); } + /** + * @group exif + * @covers \PHPExif\Exif::setAperture + * @covers \PHPExif\Exif::setIso + * @covers \PHPExif\Exif::setExposure + * @covers \PHPExif\Exif::setExposureMilliseconds + * @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 + */ + 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 '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 * From 06a75fd1c85f07c56afdbada10383189451fa227 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 10:18:50 +0200 Subject: [PATCH 21/37] Improved coverage annotations on Exif class Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/ExifTest.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index 8009eee..06e19b8 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -125,6 +125,9 @@ public function testSetData() * @covers \PHPExif\Exif::getJobtitle * @covers \PHPExif\Exif::getMimeType * @covers \PHPExif\Exif::getFileSize + * @covers \PHPExif\Exif::getHeadline + * @covers \PHPExif\Exif::getColorSpace + * @covers \PHPExif\Exif::getOrientation * @param string $accessor */ public function testUndefinedPropertiesReturnFalse($accessor) @@ -165,6 +168,9 @@ public function providerUndefinedPropertiesReturnFalse() array('getJobtitle'), array('getMimeType'), array('getFileSize'), + array('getHeadline'), + array('getColorSpace'), + array('getOrientation'), ); } @@ -499,7 +505,6 @@ public function testGetGPS() * @covers \PHPExif\Exif::setAperture * @covers \PHPExif\Exif::setIso * @covers \PHPExif\Exif::setExposure - * @covers \PHPExif\Exif::setExposureMilliseconds * @covers \PHPExif\Exif::setFocusDistance * @covers \PHPExif\Exif::setWidth * @covers \PHPExif\Exif::setHeight @@ -519,6 +524,9 @@ public function testGetGPS() * @covers \PHPExif\Exif::setJobtitle * @covers \PHPExif\Exif::setMimeType * @covers \PHPExif\Exif::setFileSize + * @covers \PHPExif\Exif::setHeadline + * @covers \PHPExif\Exif::setColorSpace + * @covers \PHPExif\Exif::setOrientation */ public function testMutatorMethodsSetInProperty() { From 52bbeef5c680988e9d7ffa717961ad370ce2d092 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 10:24:54 +0200 Subject: [PATCH 22/37] Removed unnecessary initialization of variable in Reader class Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Reader/Reader.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/PHPExif/Reader/Reader.php b/lib/PHPExif/Reader/Reader.php index 241193e..34b7bb5 100755 --- a/lib/PHPExif/Reader/Reader.php +++ b/lib/PHPExif/Reader/Reader.php @@ -72,7 +72,6 @@ public function getAdapter() public static function factory($type) { $classname = get_called_class(); - $adapter = null; switch ($type) { case self::TYPE_NATIVE: $adapter = new NativeAdapter(); @@ -84,7 +83,6 @@ public static function factory($type) throw new \InvalidArgumentException( sprintf('Unknown type "%1$s"', $type) ); - break; } return new $classname($adapter); } From 8fca517e0174d9bd6355d6b3a762bd4a9d26f6bb Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 10:25:36 +0200 Subject: [PATCH 23/37] Removed indenting level in Native mapper class Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Mapper/Native.php | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/lib/PHPExif/Mapper/Native.php b/lib/PHPExif/Mapper/Native.php index 689c983..b10f461 100644 --- a/lib/PHPExif/Mapper/Native.php +++ b/lib/PHPExif/Mapper/Native.php @@ -82,22 +82,18 @@ class Native implements MapperInterface * @var array */ protected $map = array( - //self::SECTION_COMPUTED => array( - self::APERTUREFNUMBER => Exif::APERTURE, - self::FOCUSDISTANCE => Exif::FOCAL_DISTANCE, - self::HEIGHT => Exif::HEIGHT, - self::WIDTH => Exif::WIDTH, - //), - //self::SECTION_IPTC => array( - 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::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, From 589995212d23b06bcdfb06f9cba39060b4def9af Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 10:27:40 +0200 Subject: [PATCH 24/37] Improved docblocks & removed unused variable Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/Native.php | 2 +- lib/PHPExif/Mapper/Exiftool.php | 2 +- lib/PHPExif/Mapper/MapperInterface.php | 2 +- lib/PHPExif/Mapper/Native.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/PHPExif/Adapter/Native.php b/lib/PHPExif/Adapter/Native.php index 862aa5a..c5405e9 100644 --- a/lib/PHPExif/Adapter/Native.php +++ b/lib/PHPExif/Adapter/Native.php @@ -216,7 +216,7 @@ public function getExifFromFile($file) */ public function getIptcData($file) { - $size = getimagesize($file, $info); + getimagesize($file, $info); $arrData = array(); if (isset($info['APP13'])) { $iptc = iptcparse($info['APP13']); diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php index 3baa68a..9a581a6 100644 --- a/lib/PHPExif/Mapper/Exiftool.php +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -91,7 +91,7 @@ class Exiftool implements MapperInterface * fields for the \PHPExif\Exif class * * @param array $data - * @return void + * @return array */ public function mapRawData(array $data) { diff --git a/lib/PHPExif/Mapper/MapperInterface.php b/lib/PHPExif/Mapper/MapperInterface.php index 89a20e0..5f5097e 100644 --- a/lib/PHPExif/Mapper/MapperInterface.php +++ b/lib/PHPExif/Mapper/MapperInterface.php @@ -27,7 +27,7 @@ interface MapperInterface * fields for the \PHPExif\Exif class * * @param array $data - * @return void + * @return array */ public function mapRawData(array $data); } diff --git a/lib/PHPExif/Mapper/Native.php b/lib/PHPExif/Mapper/Native.php index b10f461..4b1c31b 100644 --- a/lib/PHPExif/Mapper/Native.php +++ b/lib/PHPExif/Mapper/Native.php @@ -114,7 +114,7 @@ class Native implements MapperInterface * fields for the \PHPExif\Exif class * * @param array $data - * @return void + * @return array */ public function mapRawData(array $data) { From 32b43589f1a5be9915e290264e0670bb377c1048 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 11:06:04 +0200 Subject: [PATCH 25/37] Changed docblocks for AbstractAdapter constructor Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/AdapterAbstract.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/PHPExif/Adapter/AdapterAbstract.php b/lib/PHPExif/Adapter/AdapterAbstract.php index d4b122e..51050eb 100644 --- a/lib/PHPExif/Adapter/AdapterAbstract.php +++ b/lib/PHPExif/Adapter/AdapterAbstract.php @@ -42,7 +42,7 @@ abstract class AdapterAbstract implements AdapterInterface /** * Class constructor * - * @param array $data Optional array of data to initialize the object with + * @param array $options Optional array of data to initialize the object with */ public function __construct(array $options = array()) { From 874d64558d8a632df3faf5744b3836bd9c8fd719 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 11:10:05 +0200 Subject: [PATCH 26/37] Removed obsolete ; in docblocks Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/AdapterAbstract.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/PHPExif/Adapter/AdapterAbstract.php b/lib/PHPExif/Adapter/AdapterAbstract.php index 51050eb..9e0315a 100644 --- a/lib/PHPExif/Adapter/AdapterAbstract.php +++ b/lib/PHPExif/Adapter/AdapterAbstract.php @@ -55,7 +55,7 @@ public function __construct(array $options = array()) * Mutator for the data mapper * * @param \PHPExif\Mapper\MapperInterface $mapper - * @return \PHPExif\Adapter\AdapterInterface; + * @return \PHPExif\Adapter\AdapterInterface */ public function setMapper(MapperInterface $mapper) { @@ -85,7 +85,7 @@ public function getMapper() * Mutator for the hydrator * * @param \PHPExif\Hydrator\HydratorInterface $hydrator - * @return \PHPExif\Adapter\AdapterInterface; + * @return \PHPExif\Adapter\AdapterInterface */ public function setHydrator(HydratorInterface $hydrator) { From 86c4dac8ada202e2926bc80e3658e10ad9186518 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 12:30:34 +0200 Subject: [PATCH 27/37] Unit tests for Exiftool mapper Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Mapper/Exiftool.php | 2 +- tests/PHPExif/Mapper/ExiftoolMapperTest.php | 147 ++++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 tests/PHPExif/Mapper/ExiftoolMapperTest.php diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php index 9a581a6..ddb6661 100644 --- a/lib/PHPExif/Mapper/Exiftool.php +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -62,7 +62,6 @@ class Exiftool implements MapperInterface self::ARTIST => Exif::AUTHOR, self::MODEL => Exif::CAMERA, self::CAPTION => Exif::CAPTION, - self::CAPTIONABSTRACT => Exif::CAPTION, self::COLORSPACE => Exif::COLORSPACE, self::COPYRIGHT => Exif::COPYRIGHT, self::CREATEDATE => Exif::CREATION_DATE, @@ -84,6 +83,7 @@ class Exiftool implements MapperInterface self::TITLE => Exif::TITLE, self::YRESOLUTION => Exif::VERTICAL_RESOLUTION, self::IMAGEWIDTH => Exif::WIDTH, + self::CAPTIONABSTRACT => Exif::CAPTION, ); /** diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php new file mode 100644 index 0000000..fbe8846 --- /dev/null +++ b/tests/PHPExif/Mapper/ExiftoolMapperTest.php @@ -0,0 +1,147 @@ + + */ +class ExiftoolMapperTest extends \PHPUnit_Framework_TestCase +{ + protected $mapper; + + public function setUp() + { + $this->mapper = new \PHPExif\Mapper\Exiftool; + } + + /** + * @group mapper + * @covers \PHPExif\Mapper\Exiftool::__construct + */ + public function testMapRawDataImplementsCorrectInterface() + { + $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::CREATEDATE]); + unset($map[\PHPExif\Mapper\Exiftool::EXPOSURETIME]); + unset($map[\PHPExif\Mapper\Exiftool::FOCALLENGTH]); + + // 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::CREATEDATE => '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 testMapRawDataCorrectlyFormatsExposureTime() + { + $rawData = array( + \PHPExif\Mapper\Exiftool::EXPOSURETIME => 1/400, + ); + + $mapped = $this->mapper->mapRawData($rawData); + + $this->assertEquals('1/400', 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)); + } +} From 7b16cd4069c24b737227d94eef459089493e92ad Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Thu, 2 Apr 2015 12:36:21 +0200 Subject: [PATCH 28/37] Removed incorrect coverage tag Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Mapper/ExiftoolMapperTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php index fbe8846..d012e95 100644 --- a/tests/PHPExif/Mapper/ExiftoolMapperTest.php +++ b/tests/PHPExif/Mapper/ExiftoolMapperTest.php @@ -13,7 +13,6 @@ public function setUp() /** * @group mapper - * @covers \PHPExif\Mapper\Exiftool::__construct */ public function testMapRawDataImplementsCorrectInterface() { From a2a0272c1a4ac357bfab1a0f6fdc42007a82bc4e Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 11:49:31 +0200 Subject: [PATCH 29/37] Unit test for Native mapper Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Mapper/ExiftoolMapperTest.php | 2 +- tests/PHPExif/Mapper/NativeMapperTest.php | 169 ++++++++++++++++++++ 2 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 tests/PHPExif/Mapper/NativeMapperTest.php diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php index d012e95..061872e 100644 --- a/tests/PHPExif/Mapper/ExiftoolMapperTest.php +++ b/tests/PHPExif/Mapper/ExiftoolMapperTest.php @@ -14,7 +14,7 @@ public function setUp() /** * @group mapper */ - public function testMapRawDataImplementsCorrectInterface() + public function testClassImplementsCorrectInterface() { $this->assertInstanceOf('\\PHPExif\\Mapper\\MapperInterface', $this->mapper); } diff --git a/tests/PHPExif/Mapper/NativeMapperTest.php b/tests/PHPExif/Mapper/NativeMapperTest.php new file mode 100644 index 0000000..1f4e8de --- /dev/null +++ b/tests/PHPExif/Mapper/NativeMapperTest.php @@ -0,0 +1,169 @@ + + */ +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]); + + // 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 testMapRawDataCorrectlyFormatsExposureTime() + { + $rawData = array( + \PHPExif\Mapper\Native::EXPOSURETIME => '2/800', + ); + + $mapped = $this->mapper->mapRawData($rawData); + + $this->assertEquals('1/400', 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); + } +} From cc6fbb798fd1009cd2917b58cff25c514202a71d Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 12:01:53 +0200 Subject: [PATCH 30/37] Exclude Interfaces from coverage report Signed-off-by: Tom Van Herreweghe --- phpunit.xml.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7a43d54..7470936 100755 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -14,6 +14,7 @@ ./lib ./autoload.php + *Interface.php From 6dbc5942d9c3b1f0b23efe1dbf0a2f3aaec58655 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 12:02:05 +0200 Subject: [PATCH 31/37] Added @covers annotation for the NoAdapterException Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/Reader/ReaderTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/PHPExif/Reader/ReaderTest.php b/tests/PHPExif/Reader/ReaderTest.php index f3fa22b..82aa133 100644 --- a/tests/PHPExif/Reader/ReaderTest.php +++ b/tests/PHPExif/Reader/ReaderTest.php @@ -53,6 +53,7 @@ public function testGetAdapterFromProperty() /** * @group reader * @covers \PHPExif\Reader\Reader::getAdapter + * @covers \PHPExif\Adapter\NoAdapterException * @expectedException \PHPExif\Adapter\NoAdapterException */ public function testGetAdapterThrowsExceptionWhenNoAdapterIsSet() From a862beadffe1ac00cc939e50310580fb48ac64d6 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 12:13:23 +0200 Subject: [PATCH 32/37] Tried mocking proc_open function for coverage Signed-off-by: Tom Van Herreweghe --- .../PHPExif/Adapter/ExiftoolProcOpenTest.php | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/PHPExif/Adapter/ExiftoolProcOpenTest.php diff --git a/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php b/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php new file mode 100644 index 0000000..509bd66 --- /dev/null +++ b/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php @@ -0,0 +1,46 @@ + + */ + class ExiftoolProcOpenTest 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::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); + } + } +} From 795fab58b9ff0626e5a2d18e245cebd397a942cc Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 12:56:24 +0200 Subject: [PATCH 33/37] Corrected stubbing of root function Signed-off-by: Tom Van Herreweghe --- .../PHPExif/Adapter/ExiftoolProcOpenTest.php | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php b/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php index 509bd66..9d9bd39 100644 --- a/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php +++ b/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php @@ -1,14 +1,28 @@ */ @@ -21,11 +35,21 @@ class ExiftoolProcOpenTest extends \PHPUnit_Framework_TestCase 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() { @@ -39,8 +63,6 @@ public function testGetCliOutput() 'pwd' ) ); - - $this->assertInternalType('string', $result); } } } From 476367b4b260d85a0a8d4459cc64bf4290bf8bdd Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 16:46:39 +0200 Subject: [PATCH 34/37] Add GPS code Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Adapter/Exiftool.php | 8 ++- lib/PHPExif/Exif.php | 28 +++++++++ lib/PHPExif/Mapper/Exiftool.php | 66 +++++++++++++++++++++ lib/PHPExif/Mapper/Native.php | 46 ++++++++++++++ tests/PHPExif/ExifTest.php | 2 + tests/PHPExif/Mapper/ExiftoolMapperTest.php | 2 + tests/PHPExif/Mapper/NativeMapperTest.php | 2 + 7 files changed, 152 insertions(+), 2 deletions(-) diff --git a/lib/PHPExif/Adapter/Exiftool.php b/lib/PHPExif/Adapter/Exiftool.php index d8f715b..f4eb648 100644 --- a/lib/PHPExif/Adapter/Exiftool.php +++ b/lib/PHPExif/Adapter/Exiftool.php @@ -100,12 +100,15 @@ public function getToolPath() */ public function getExifFromFile($file) { + $gpsFormat = '%d deg %d\' %.4f\"'; + $result = $this->getCliOutput( sprintf( - '%1$s%3$s -j %2$s', + '%1$s%3$s -j -c "%4$s" %2$s', $this->getToolPath(), $file, - $this->numeric ? ' -n' : '' + $this->numeric ? ' -n' : '', + $gpsFormat ) ); @@ -113,6 +116,7 @@ public function getExifFromFile($file) // map the data: $mapper = $this->getMapper(); + $mapper->setNumeric($this->numeric); $mappedData = $mapper->mapRawData(reset($data)); // hydrate a new Exif object diff --git a/lib/PHPExif/Exif.php b/lib/PHPExif/Exif.php index f9c2b2f..1ce5a5e 100755 --- a/lib/PHPExif/Exif.php +++ b/lib/PHPExif/Exif.php @@ -47,6 +47,7 @@ class Exif const TITLE = 'title'; const VERTICAL_RESOLUTION = 'verticalResolution'; const WIDTH = 'width'; + const GPS = 'gps'; /** * The mapped EXIF data @@ -808,4 +809,31 @@ public function setOrientation($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 array $value + * @return \PHPExif\Exif + */ + public function setGPS(array $value) + { + $this->data[self::GPS] = $value; + + return $this; + } } diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php index ddb6661..cc66335 100644 --- a/lib/PHPExif/Mapper/Exiftool.php +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -50,6 +50,8 @@ class Exiftool implements MapperInterface const TITLE = 'Title'; const XRESOLUTION = 'XResolution'; const YRESOLUTION = 'YResolution'; + const GPSLATITUDEREF = 'GPSLatitudeRef'; + const GPSLONGITUDEREF = 'GPSLongitudeRef'; /** * Maps the ExifTool fields to the fields of @@ -84,8 +86,28 @@ class Exiftool implements MapperInterface self::YRESOLUTION => Exif::VERTICAL_RESOLUTION, self::IMAGEWIDTH => Exif::WIDTH, self::CAPTIONABSTRACT => Exif::CAPTION, + self::GPSLATITUDEREF => Exif::GPS, + self::GPSLONGITUDEREF => 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 @@ -96,6 +118,7 @@ class Exiftool implements MapperInterface 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 @@ -122,12 +145,55 @@ public function mapRawData(array $data) $focalLengthParts = explode(' ', $value); $value = (int) reset($focalLengthParts); break; + case self::GPSLATITUDEREF: + $gpsData['lat'] = $this->extractGPSCoordinates($value); + break; + case self::GPSLONGITUDEREF: + $gpsData['lon'] = $this->extractGPSCoordinates($value); + break; } // set end result $mappedData[$key] = $value; } + // add GPS coordinates, if available + if (count($gpsData) === 2) { + $latitude = $gpsData['lat']; + $longitude = $gpsData['lon']; + + if ($latitude !== false && $longitude !== false) { + $gpsLocation = sprintf( + '%s,%s', + (strtoupper($data[self::GPSLATITUDEREF][0]) === 'S' ? -1 : 1) * $latitude, + (strtoupper($data[self::GPSLONGITUDEREF][0]) === 'W' ? -1 : 1) * $longitude + ); + + $key = $this->map[self::GPSLATITUDEREF]; + + $mappedData[$key] = $gpsLocation; + } + } + 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 index 4b1c31b..8f93ce1 100644 --- a/lib/PHPExif/Mapper/Native.php +++ b/lib/PHPExif/Mapper/Native.php @@ -49,6 +49,8 @@ class Native implements MapperInterface const WIDTH = 'Width'; const XRESOLUTION = 'XResolution'; const YRESOLUTION = 'YResolution'; + const GPSLATITUDEREF = 'GPSLatitudeRef'; + const GPSLONGITUDEREF = 'GPSLongitudeRef'; const SECTION_FILE = 'FILE'; const SECTION_COMPUTED = 'COMPUTED'; @@ -107,6 +109,8 @@ class Native implements MapperInterface self::SOFTWARE => Exif::SOFTWARE, self::XRESOLUTION => Exif::HORIZONTAL_RESOLUTION, self::YRESOLUTION => Exif::VERTICAL_RESOLUTION, + self::GPSLATITUDEREF => Exif::GPS, + self::GPSLONGITUDEREF => Exif::GPS, ); /** @@ -119,6 +123,7 @@ class Native implements MapperInterface 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); @@ -157,12 +162,27 @@ public function mapRawData(array $data) $resolutionParts = explode('/', $value); $value = (int)reset($resolutionParts); break; + case self::GPSLATITUDEREF: + $gpsData['lat'] = $this->extractGPSCoordinate($value); + break; + case self::GPSLONGITUDEREF: + $gpsData['lon'] = $this->extractGPSCoordinate($value); + break; } // set end result $mappedData[$key] = $value; } + if (count($gpsData) === 2) { + $gpsLocation = sprintf( + '%s,%s', + (strtoupper($data[self::GPSLATITUDEREF][0]) === 'S' ? -1 : 1) * $gpsData['lat'], + (strtoupper($data[self::GPSLONGITUDEREF][0]) === 'W' ? -1 : 1) * $gpsData['lon'] + ); + $mappedData[Exif::GPS] = $gpsLocation; + } + return $mappedData; } @@ -176,4 +196,30 @@ 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, 'normalizeGPSComponent'), $components); + + return intval($components[0]) + (intval($components[1]) / 60) + (floatval($components[2]) / 3600); + } + + /** + * Normalize GPS coordinates components + * + * @param mixed $component + * @return int|float + */ + protected function normalizeGPSComponent($component) + { + $parts = explode('/', $component); + + return count($parts) === 1 ? $parts[0] : (int) reset($parts) / (int) end($parts); + } } diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index 06e19b8..06d34e9 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -549,6 +549,8 @@ public function testMutatorMethodsSetInProperty() break; case 'focalDistance': $setter = 'setFocusDistance'; + case 'gps': + break; default: $this->exif->$setter($expected); $propertyValue = $reflProp->getValue($this->exif); diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php index 061872e..97fca37 100644 --- a/tests/PHPExif/Mapper/ExiftoolMapperTest.php +++ b/tests/PHPExif/Mapper/ExiftoolMapperTest.php @@ -47,6 +47,8 @@ public function testMapRawDataMapsFieldsCorrectly() unset($map[\PHPExif\Mapper\Exiftool::CREATEDATE]); unset($map[\PHPExif\Mapper\Exiftool::EXPOSURETIME]); unset($map[\PHPExif\Mapper\Exiftool::FOCALLENGTH]); + unset($map[\PHPExif\Mapper\Exiftool::GPSLATITUDEREF]); + unset($map[\PHPExif\Mapper\Exiftool::GPSLONGITUDEREF]); // create raw data $keys = array_keys($map); diff --git a/tests/PHPExif/Mapper/NativeMapperTest.php b/tests/PHPExif/Mapper/NativeMapperTest.php index 1f4e8de..b1d4882 100644 --- a/tests/PHPExif/Mapper/NativeMapperTest.php +++ b/tests/PHPExif/Mapper/NativeMapperTest.php @@ -47,6 +47,8 @@ public function testMapRawDataMapsFieldsCorrectly() unset($map[\PHPExif\Mapper\Native::FOCALLENGTH]); unset($map[\PHPExif\Mapper\Native::XRESOLUTION]); unset($map[\PHPExif\Mapper\Native::YRESOLUTION]); + unset($map[\PHPExif\Mapper\Native::GPSLATITUDEREF]); + unset($map[\PHPExif\Mapper\Native::GPSLONGITUDEREF]); // create raw data $keys = array_keys($map); From 1e2e623a2fffcf93e49299f1ce1ed1d383bca6d9 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 16:57:31 +0200 Subject: [PATCH 35/37] More unit tests for Exif (GPS added) Signed-off-by: Tom Van Herreweghe --- tests/PHPExif/ExifTest.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index 06d34e9..1a3d741 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -128,6 +128,7 @@ public function testSetData() * @covers \PHPExif\Exif::getHeadline * @covers \PHPExif\Exif::getColorSpace * @covers \PHPExif\Exif::getOrientation + * @covers \PHPExif\Exif::getGPS * @param string $accessor */ public function testUndefinedPropertiesReturnFalse($accessor) @@ -171,6 +172,7 @@ public function providerUndefinedPropertiesReturnFalse() array('getHeadline'), array('getColorSpace'), array('getOrientation'), + array('getGPS'), ); } @@ -527,6 +529,7 @@ public function testGetGPS() * @covers \PHPExif\Exif::setHeadline * @covers \PHPExif\Exif::setColorSpace * @covers \PHPExif\Exif::setOrientation + * @covers \PHPExif\Exif::setGPS */ public function testMutatorMethodsSetInProperty() { @@ -547,10 +550,14 @@ public function testMutatorMethodsSetInProperty() $propertyValue = $reflProp->getValue($this->exif); $this->assertSame($now, $propertyValue[$value]); break; - case 'focalDistance': - $setter = 'setFocusDistance'; case 'gps': + $coords = '40.333452380556,-20.167314813889'; + $this->exif->$setter($coords); + $propertyValue = $reflProp->getValue($this->exif); + $this->assertEquals($expected, $propertyValue[$value]); break; + case 'focalDistance': + $setter = 'setFocusDistance'; default: $this->exif->$setter($expected); $propertyValue = $reflProp->getValue($this->exif); From 401686cce2af53ab06fc262f1c9cfde8cf8eedfc Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 17:15:15 +0200 Subject: [PATCH 36/37] Unit tests for GPS stuff Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Exif.php | 4 +- lib/PHPExif/Mapper/Exiftool.php | 18 ++++---- lib/PHPExif/Mapper/Native.php | 16 +++---- tests/PHPExif/ExifTest.php | 3 +- tests/PHPExif/Mapper/ExiftoolMapperTest.php | 46 ++++++++++++++++++++- tests/PHPExif/Mapper/NativeMapperTest.php | 23 ++++++++++- 6 files changed, 86 insertions(+), 24 deletions(-) diff --git a/lib/PHPExif/Exif.php b/lib/PHPExif/Exif.php index 1ce5a5e..ba5080a 100755 --- a/lib/PHPExif/Exif.php +++ b/lib/PHPExif/Exif.php @@ -827,10 +827,10 @@ public function getGPS() /** * Sets the GPS coordinates * - * @param array $value + * @param string $value * @return \PHPExif\Exif */ - public function setGPS(array $value) + public function setGPS($value) { $this->data[self::GPS] = $value; diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php index cc66335..62f838e 100644 --- a/lib/PHPExif/Mapper/Exiftool.php +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -50,8 +50,8 @@ class Exiftool implements MapperInterface const TITLE = 'Title'; const XRESOLUTION = 'XResolution'; const YRESOLUTION = 'YResolution'; - const GPSLATITUDEREF = 'GPSLatitudeRef'; - const GPSLONGITUDEREF = 'GPSLongitudeRef'; + const GPSLATITUDE = 'GPSLatitude'; + const GPSLONGITUDE = 'GPSLongitude'; /** * Maps the ExifTool fields to the fields of @@ -86,8 +86,8 @@ class Exiftool implements MapperInterface self::YRESOLUTION => Exif::VERTICAL_RESOLUTION, self::IMAGEWIDTH => Exif::WIDTH, self::CAPTIONABSTRACT => Exif::CAPTION, - self::GPSLATITUDEREF => Exif::GPS, - self::GPSLONGITUDEREF => Exif::GPS, + self::GPSLATITUDE => Exif::GPS, + self::GPSLONGITUDE => Exif::GPS, ); /** @@ -145,10 +145,10 @@ public function mapRawData(array $data) $focalLengthParts = explode(' ', $value); $value = (int) reset($focalLengthParts); break; - case self::GPSLATITUDEREF: + case self::GPSLATITUDE: $gpsData['lat'] = $this->extractGPSCoordinates($value); break; - case self::GPSLONGITUDEREF: + case self::GPSLONGITUDE: $gpsData['lon'] = $this->extractGPSCoordinates($value); break; } @@ -165,11 +165,11 @@ public function mapRawData(array $data) if ($latitude !== false && $longitude !== false) { $gpsLocation = sprintf( '%s,%s', - (strtoupper($data[self::GPSLATITUDEREF][0]) === 'S' ? -1 : 1) * $latitude, - (strtoupper($data[self::GPSLONGITUDEREF][0]) === 'W' ? -1 : 1) * $longitude + (strtoupper($data['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $latitude, + (strtoupper($data['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $longitude ); - $key = $this->map[self::GPSLATITUDEREF]; + $key = $this->map[self::GPSLATITUDE]; $mappedData[$key] = $gpsLocation; } diff --git a/lib/PHPExif/Mapper/Native.php b/lib/PHPExif/Mapper/Native.php index 8f93ce1..ab68853 100644 --- a/lib/PHPExif/Mapper/Native.php +++ b/lib/PHPExif/Mapper/Native.php @@ -49,8 +49,8 @@ class Native implements MapperInterface const WIDTH = 'Width'; const XRESOLUTION = 'XResolution'; const YRESOLUTION = 'YResolution'; - const GPSLATITUDEREF = 'GPSLatitudeRef'; - const GPSLONGITUDEREF = 'GPSLongitudeRef'; + const GPSLATITUDE = 'GPSLatitude'; + const GPSLONGITUDE = 'GPSLongitude'; const SECTION_FILE = 'FILE'; const SECTION_COMPUTED = 'COMPUTED'; @@ -109,8 +109,8 @@ class Native implements MapperInterface self::SOFTWARE => Exif::SOFTWARE, self::XRESOLUTION => Exif::HORIZONTAL_RESOLUTION, self::YRESOLUTION => Exif::VERTICAL_RESOLUTION, - self::GPSLATITUDEREF => Exif::GPS, - self::GPSLONGITUDEREF => Exif::GPS, + self::GPSLATITUDE => Exif::GPS, + self::GPSLONGITUDE => Exif::GPS, ); /** @@ -162,10 +162,10 @@ public function mapRawData(array $data) $resolutionParts = explode('/', $value); $value = (int)reset($resolutionParts); break; - case self::GPSLATITUDEREF: + case self::GPSLATITUDE: $gpsData['lat'] = $this->extractGPSCoordinate($value); break; - case self::GPSLONGITUDEREF: + case self::GPSLONGITUDE: $gpsData['lon'] = $this->extractGPSCoordinate($value); break; } @@ -177,8 +177,8 @@ public function mapRawData(array $data) if (count($gpsData) === 2) { $gpsLocation = sprintf( '%s,%s', - (strtoupper($data[self::GPSLATITUDEREF][0]) === 'S' ? -1 : 1) * $gpsData['lat'], - (strtoupper($data[self::GPSLONGITUDEREF][0]) === 'W' ? -1 : 1) * $gpsData['lon'] + (strtoupper($data['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $gpsData['lat'], + (strtoupper($data['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $gpsData['lon'] ); $mappedData[Exif::GPS] = $gpsLocation; } diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php index 1a3d741..964a917 100755 --- a/tests/PHPExif/ExifTest.php +++ b/tests/PHPExif/ExifTest.php @@ -552,9 +552,10 @@ public function testMutatorMethodsSetInProperty() break; case 'gps': $coords = '40.333452380556,-20.167314813889'; + $setter = 'setGPS'; $this->exif->$setter($coords); $propertyValue = $reflProp->getValue($this->exif); - $this->assertEquals($expected, $propertyValue[$value]); + $this->assertEquals($coords, $propertyValue[$value]); break; case 'focalDistance': $setter = 'setFocusDistance'; diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php index 97fca37..3cff4d6 100644 --- a/tests/PHPExif/Mapper/ExiftoolMapperTest.php +++ b/tests/PHPExif/Mapper/ExiftoolMapperTest.php @@ -47,8 +47,8 @@ public function testMapRawDataMapsFieldsCorrectly() unset($map[\PHPExif\Mapper\Exiftool::CREATEDATE]); unset($map[\PHPExif\Mapper\Exiftool::EXPOSURETIME]); unset($map[\PHPExif\Mapper\Exiftool::FOCALLENGTH]); - unset($map[\PHPExif\Mapper\Exiftool::GPSLATITUDEREF]); - unset($map[\PHPExif\Mapper\Exiftool::GPSLONGITUDEREF]); + unset($map[\PHPExif\Mapper\Exiftool::GPSLATITUDE]); + unset($map[\PHPExif\Mapper\Exiftool::GPSLONGITUDE]); // create raw data $keys = array_keys($map); @@ -145,4 +145,46 @@ public function testMapRawDataCorrectlyFormatsFocalLength() $this->assertEquals(15, reset($mapped)); } + + /** + * @group mapper + * @covers \PHPExif\Mapper\Exiftool::mapRawData + */ + public function testMapRawDataCorrectlyFormatsGPSData() + { + $this->mapper->setNumeric(false); + $result = $this->mapper->mapRawData( + array( + 'GPSLatitude' => '40 deg 20\' 0.42857" N', + 'GPSLatitudeRef' => 'North', + 'GPSLongitude' => '20 deg 10\' 2.33333" W', + '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( + 'GPSLatitude' => '40.333452381', + 'GPSLatitudeRef' => 'North', + 'GPSLongitude' => '20.167314814', + 'GPSLongitudeRef' => 'West', + ) + ); + + $expected = '40.333452381,-20.167314814'; + $this->assertCount(1, $result); + $this->assertEquals($expected, reset($result)); + } + } diff --git a/tests/PHPExif/Mapper/NativeMapperTest.php b/tests/PHPExif/Mapper/NativeMapperTest.php index b1d4882..d6e78fc 100644 --- a/tests/PHPExif/Mapper/NativeMapperTest.php +++ b/tests/PHPExif/Mapper/NativeMapperTest.php @@ -47,8 +47,8 @@ public function testMapRawDataMapsFieldsCorrectly() unset($map[\PHPExif\Mapper\Native::FOCALLENGTH]); unset($map[\PHPExif\Mapper\Native::XRESOLUTION]); unset($map[\PHPExif\Mapper\Native::YRESOLUTION]); - unset($map[\PHPExif\Mapper\Native::GPSLATITUDEREF]); - unset($map[\PHPExif\Mapper\Native::GPSLONGITUDEREF]); + unset($map[\PHPExif\Mapper\Native::GPSLATITUDE]); + unset($map[\PHPExif\Mapper\Native::GPSLONGITUDE]); // create raw data $keys = array_keys($map); @@ -168,4 +168,23 @@ public function testMapRawDataFlattensRawDataWithSections() ); $this->assertEquals($expected, $keys); } + + /** + * @group mapper + * @covers \PHPExif\Mapper\Native::mapRawData + */ + public function testMapRawDataCorrectlyFormatsGPSData() + { + $result = $this->mapper->mapRawData( + array( + 'GPSLatitude' => array('40/1', '20/1', '15/35'), + 'GPSLatitudeRef' => 'N', + 'GPSLongitude' => array('20/1', '10/1', '35/15'), + 'GPSLongitudeRef' => 'W', + ) + ); + + $expected = '40.333452380952,-20.167314814815'; + $this->assertEquals($expected, reset($result)); + } } From 1d4a96bcd49967ddeea90e30069962cda4bcbb5e Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Fri, 3 Apr 2015 18:00:59 +0200 Subject: [PATCH 37/37] Covered extra paths for Exiftool mapper test Signed-off-by: Tom Van Herreweghe --- lib/PHPExif/Mapper/Exiftool.php | 4 ++ tests/PHPExif/Mapper/ExiftoolMapperTest.php | 51 ++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php index 62f838e..2be4c43 100644 --- a/lib/PHPExif/Mapper/Exiftool.php +++ b/lib/PHPExif/Mapper/Exiftool.php @@ -172,7 +172,11 @@ public function mapRawData(array $data) $key = $this->map[self::GPSLATITUDE]; $mappedData[$key] = $gpsLocation; + } else { + unset($mappedData[$this->map[self::GPSLATITUDE]]); } + } else { + unset($mappedData[$this->map[self::GPSLATITUDE]]); } return $mappedData; diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php index 3cff4d6..485cda8 100644 --- a/tests/PHPExif/Mapper/ExiftoolMapperTest.php +++ b/tests/PHPExif/Mapper/ExiftoolMapperTest.php @@ -186,5 +186,54 @@ public function testMapRawDataCorrectlyFormatsNumericGPSData() $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( + 'GPSLatitude' => '40.333452381', + 'GPSLatitudeRef' => 'North', + 'GPSLongitude' => '20.167314814', + 'GPSLongitudeRef' => 'West', + ) + ); + + $this->assertCount(0, $result); + } + + /** + * @group mapper + * @covers \PHPExif\Mapper\Exiftool::mapRawData + */ + public function testMapRawDataCorrectlyIgnoresIncompleteGPSData() + { + $result = $this->mapper->mapRawData( + array( + 'GPSLatitude' => '40.333452381', + '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)); + } }