diff --git a/lib/PHPExif/Adapter/AdapterAbstract.php b/lib/PHPExif/Adapter/AdapterAbstract.php
index 1e4450f..9e0315a 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,10 +24,25 @@
*/
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
*
- * @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())
{
@@ -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/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/Exiftool.php b/lib/PHPExif/Adapter/Exiftool.php
index 8e6bbe6..f4eb648 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
*
@@ -109,8 +113,16 @@ public function getExifFromFile($file)
);
$data = json_decode($result, true);
- $mappedData = $this->mapData(reset($data));
- $exif = new Exif($mappedData);
+
+ // map the data:
+ $mapper = $this->getMapper();
+ $mapper->setNumeric($this->numeric);
+ $mappedData = $mapper->mapRawData(reset($data));
+
+ // hydrate a new Exif object
+ $exif = new Exif();
+ $hydrator = $this->getHydrator();
+ $hydrator->hydrate($exif, $mappedData);
$exif->setRawData(reset($data));
return $exif;
@@ -148,96 +160,4 @@ 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/lib/PHPExif/Adapter/Native.php b/lib/PHPExif/Adapter/Native.php
index a7d6756..c5405e9 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;
@@ -224,164 +236,4 @@ 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/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/Exif.php b/lib/PHPExif/Exif.php
index 4f39c6d..ba5080a 100755
--- a/lib/PHPExif/Exif.php
+++ b/lib/PHPExif/Exif.php
@@ -133,6 +133,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 +160,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 +187,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 +214,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 +241,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 +268,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 +295,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 +322,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 +365,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 +392,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 +419,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 +446,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 +473,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 +500,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 +527,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 +554,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 +581,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 +608,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 +635,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 +662,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,52 +689,104 @@ 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
*
- * @return string
+ * @return string|boolean
*/
public function getColorSpace()
{
if (!isset($this->data[self::COLORSPACE])) {
return false;
}
-
+
return $this->data[self::COLORSPACE];
}
+ /**
+ * Sets the colorspace
+ *
+ * @param string $value
+ * @return \PHPExif\Exif
+ */
+ public function setColorSpace($value)
+ {
+ $this->data[self::COLORSPACE] = $value;
+
+ return $this;
+ }
+
/**
* Returns the mimetype, if it exists
*
- * @return string
+ * @return string|boolean
*/
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|boolean
*/
public function getFileSize()
{
if (!isset($this->data[self::FILESIZE])) {
return false;
}
-
+
return $this->data[self::FILESIZE];
}
+ /**
+ * Sets the filesize
+ *
+ * @param int $value
+ * @return \PHPExif\Exif
+ */
+ public function setFileSize($value)
+ {
+ $this->data[self::FILESIZE] = $value;
+
+ return $this;
+ }
+
/**
* Returns the orientation, if it exists
*
- * @return integer
+ * @return int|boolean
*/
public function getOrientation()
{
@@ -485,6 +797,19 @@ public function getOrientation()
return $this->data[self::ORIENTATION];
}
+ /**
+ * Sets the orientation
+ *
+ * @param int $value
+ * @return \PHPExif\Exif
+ */
+ public function setOrientation($value)
+ {
+ $this->data[self::ORIENTATION] = $value;
+
+ return $this;
+ }
+
/**
* Returns GPS coordinates, if it exists
*
@@ -498,4 +823,17 @@ public function getGPS()
return $this->data[self::GPS];
}
+
+ /**
+ * Sets the GPS coordinates
+ *
+ * @param string $value
+ * @return \PHPExif\Exif
+ */
+ public function setGPS($value)
+ {
+ $this->data[self::GPS] = $value;
+
+ return $this;
+ }
}
diff --git a/lib/PHPExif/Hydrator/HydratorInterface.php b/lib/PHPExif/Hydrator/HydratorInterface.php
new file mode 100644
index 0000000..d884327
--- /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
+ * @codeCoverageIgnore
+ */
+
+namespace PHPExif\Hydrator;
+
+/**
+ * PHP Exif Hydrator
+ *
+ * Defines the interface for a hydrator
+ *
+ * @category PHPExif
+ * @package Hydrator
+ */
+interface HydratorInterface
+{
+ /**
+ * Hydrates given array of data into the given Exif object
+ *
+ * @param object $object
+ * @param array $data
+ * @return void
+ */
+ public function hydrate($object, array $data);
+}
diff --git a/lib/PHPExif/Hydrator/Mutator.php b/lib/PHPExif/Hydrator/Mutator.php
new file mode 100644
index 0000000..164d57c
--- /dev/null
+++ b/lib/PHPExif/Hydrator/Mutator.php
@@ -0,0 +1,55 @@
+
+ * @license http://github.com/miljar/PHPExif/blob/master/LICENSE MIT License
+ * @category PHPExif
+ * @package Hydrator
+ */
+
+namespace PHPExif\Hydrator;
+
+/**
+ * PHP Exif Mutator Hydrator
+ *
+ * Hydrates an object by setting data with
+ * the class mutator methods
+ *
+ * @category PHPExif
+ * @package Hydrator
+ */
+class Mutator implements HydratorInterface
+{
+ /**
+ * Hydrates given array of data into the given Exif object
+ *
+ * @param object $object
+ * @param array $data
+ * @return void
+ */
+ public function hydrate($object, array $data)
+ {
+ foreach ($data as $property => $value) {
+ $mutator = $this->determineMutator($property);
+
+ if (method_exists($object, $mutator)) {
+ $object->$mutator($value);
+ }
+ }
+ }
+
+ /**
+ * Determines the name of the mutator method for given property name
+ *
+ * @param string $property The property to determine the mutator for
+ * @return string The name of the mutator method
+ */
+ protected function determineMutator($property)
+ {
+ $method = 'set' . ucfirst($property);
+ return $method;
+ }
+}
diff --git a/lib/PHPExif/Mapper/Exiftool.php b/lib/PHPExif/Mapper/Exiftool.php
new file mode 100644
index 0000000..2be4c43
--- /dev/null
+++ b/lib/PHPExif/Mapper/Exiftool.php
@@ -0,0 +1,203 @@
+
+ * @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 CREATEDATE = 'CreateDate';
+ 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';
+ const GPSLATITUDE = 'GPSLatitude';
+ const GPSLONGITUDE = 'GPSLongitude';
+
+ /**
+ * Maps the ExifTool fields to the fields of
+ * the \PHPExif\Exif class
+ *
+ * @var array
+ */
+ protected $map = array(
+ self::APERTURE => Exif::APERTURE,
+ self::ARTIST => Exif::AUTHOR,
+ self::MODEL => Exif::CAMERA,
+ self::CAPTION => Exif::CAPTION,
+ self::COLORSPACE => Exif::COLORSPACE,
+ self::COPYRIGHT => Exif::COPYRIGHT,
+ self::CREATEDATE => Exif::CREATION_DATE,
+ self::CREDIT => Exif::CREDIT,
+ self::EXPOSURETIME => Exif::EXPOSURE,
+ self::FILESIZE => Exif::FILESIZE,
+ self::FOCALLENGTH => Exif::FOCAL_LENGTH,
+ self::APPROXIMATEFOCUSDISTANCE => Exif::FOCAL_DISTANCE,
+ self::HEADLINE => Exif::HEADLINE,
+ self::IMAGEHEIGHT => Exif::HEIGHT,
+ self::XRESOLUTION => Exif::HORIZONTAL_RESOLUTION,
+ self::ISO => Exif::ISO,
+ self::JOBTITLE => Exif::JOB_TITLE,
+ self::KEYWORDS => Exif::KEYWORDS,
+ self::MIMETYPE => Exif::MIMETYPE,
+ self::ORIENTATION => Exif::ORIENTATION,
+ self::SOFTWARE => Exif::SOFTWARE,
+ self::SOURCE => Exif::SOURCE,
+ self::TITLE => Exif::TITLE,
+ self::YRESOLUTION => Exif::VERTICAL_RESOLUTION,
+ self::IMAGEWIDTH => Exif::WIDTH,
+ self::CAPTIONABSTRACT => Exif::CAPTION,
+ self::GPSLATITUDE => Exif::GPS,
+ self::GPSLONGITUDE => Exif::GPS,
+ );
+
+ /**
+ * @var bool
+ */
+ protected $numeric = true;
+
+ /**
+ * Mutator method for the numeric property
+ *
+ * @param bool $numeric
+ * @return \PHPExif\Mapper\Exiftool
+ */
+ public function setNumeric($numeric)
+ {
+ $this->numeric = (bool)$numeric;
+
+ return $this;
+ }
+
+ /**
+ * Maps the array of raw source data to the correct
+ * fields for the \PHPExif\Exif class
+ *
+ * @param array $data
+ * @return array
+ */
+ public function mapRawData(array $data)
+ {
+ $mappedData = array();
+ $gpsData = array();
+ foreach ($data as $field => $value) {
+ if (!array_key_exists($field, $this->map)) {
+ // silently ignore unknown fields
+ continue;
+ }
+
+ $key = $this->map[$field];
+
+ // manipulate the value if necessary
+ switch ($field) {
+ case self::APERTURE:
+ $value = sprintf('f/%01.1f', $value);
+ break;
+ case self::APPROXIMATEFOCUSDISTANCE:
+ $value = sprintf('%1$sm', $value);
+ break;
+ case self::CREATEDATE:
+ $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;
+ case self::GPSLATITUDE:
+ $gpsData['lat'] = $this->extractGPSCoordinates($value);
+ break;
+ case self::GPSLONGITUDE:
+ $gpsData['lon'] = $this->extractGPSCoordinates($value);
+ break;
+ }
+
+ // set end result
+ $mappedData[$key] = $value;
+ }
+
+ // add GPS coordinates, if available
+ if (count($gpsData) === 2) {
+ $latitude = $gpsData['lat'];
+ $longitude = $gpsData['lon'];
+
+ if ($latitude !== false && $longitude !== false) {
+ $gpsLocation = sprintf(
+ '%s,%s',
+ (strtoupper($data['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $latitude,
+ (strtoupper($data['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $longitude
+ );
+
+ $key = $this->map[self::GPSLATITUDE];
+
+ $mappedData[$key] = $gpsLocation;
+ } else {
+ unset($mappedData[$this->map[self::GPSLATITUDE]]);
+ }
+ } else {
+ unset($mappedData[$this->map[self::GPSLATITUDE]]);
+ }
+
+ 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/MapperInterface.php b/lib/PHPExif/Mapper/MapperInterface.php
new file mode 100644
index 0000000..5f5097e
--- /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
+ * @codeCoverageIgnore
+ */
+
+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 array
+ */
+ 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..ab68853
--- /dev/null
+++ b/lib/PHPExif/Mapper/Native.php
@@ -0,0 +1,225 @@
+
+ * @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 GPSLATITUDE = 'GPSLatitude';
+ const GPSLONGITUDE = 'GPSLongitude';
+
+ const SECTION_FILE = 'FILE';
+ const SECTION_COMPUTED = 'COMPUTED';
+ const SECTION_IFD0 = 'IFD0';
+ const SECTION_THUMBNAIL = 'THUMBNAIL';
+ const SECTION_COMMENT = 'COMMENT';
+ const SECTION_EXIF = 'EXIF';
+ const SECTION_ALL = 'ANY_TAG';
+ const SECTION_IPTC = 'IPTC';
+
+ /**
+ * A list of section names
+ *
+ * @var array
+ */
+ protected $sections = array(
+ self::SECTION_FILE,
+ self::SECTION_COMPUTED,
+ self::SECTION_IFD0,
+ self::SECTION_THUMBNAIL,
+ self::SECTION_COMMENT,
+ self::SECTION_EXIF,
+ self::SECTION_ALL,
+ self::SECTION_IPTC,
+ );
+
+ /**
+ * Maps the ExifTool fields to the fields of
+ * the \PHPExif\Exif class
+ *
+ * @var array
+ */
+ protected $map = array(
+ self::APERTUREFNUMBER => Exif::APERTURE,
+ self::FOCUSDISTANCE => Exif::FOCAL_DISTANCE,
+ self::HEIGHT => Exif::HEIGHT,
+ self::WIDTH => Exif::WIDTH,
+ self::CAPTION => Exif::CAPTION,
+ self::COPYRIGHT => Exif::COPYRIGHT,
+ self::CREDIT => Exif::CREDIT,
+ self::HEADLINE => Exif::HEADLINE,
+ self::JOBTITLE => Exif::JOB_TITLE,
+ self::KEYWORDS => Exif::KEYWORDS,
+ self::SOURCE => Exif::SOURCE,
+ self::TITLE => Exif::TITLE,
+ self::ARTIST => Exif::AUTHOR,
+ self::MODEL => Exif::CAMERA,
+ self::COLORSPACE => Exif::COLORSPACE,
+ self::DATETIMEORIGINAL => Exif::CREATION_DATE,
+ self::EXPOSURETIME => Exif::EXPOSURE,
+ self::FILESIZE => Exif::FILESIZE,
+ self::FOCALLENGTH => Exif::FOCAL_LENGTH,
+ self::ISOSPEEDRATINGS => Exif::ISO,
+ self::MIMETYPE => Exif::MIMETYPE,
+ self::ORIENTATION => Exif::ORIENTATION,
+ self::SOFTWARE => Exif::SOFTWARE,
+ self::XRESOLUTION => Exif::HORIZONTAL_RESOLUTION,
+ self::YRESOLUTION => Exif::VERTICAL_RESOLUTION,
+ self::GPSLATITUDE => Exif::GPS,
+ self::GPSLONGITUDE => Exif::GPS,
+ );
+
+ /**
+ * Maps the array of raw source data to the correct
+ * fields for the \PHPExif\Exif class
+ *
+ * @param array $data
+ * @return array
+ */
+ public function mapRawData(array $data)
+ {
+ $mappedData = array();
+ $gpsData = array();
+ foreach ($data as $field => $value) {
+ if ($this->isSection($field) && is_array($value)) {
+ $subData = $this->mapRawData($value);
+
+ $mappedData = array_merge($mappedData, $subData);
+ continue;
+ }
+
+ if (!array_key_exists($field, $this->map)) {
+ // silently ignore unknown fields
+ continue;
+ }
+
+ $key = $this->map[$field];
+
+ // manipulate the value if necessary
+ switch ($field) {
+ case self::DATETIMEORIGINAL:
+ $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;
+ case self::GPSLATITUDE:
+ $gpsData['lat'] = $this->extractGPSCoordinate($value);
+ break;
+ case self::GPSLONGITUDE:
+ $gpsData['lon'] = $this->extractGPSCoordinate($value);
+ break;
+ }
+
+ // set end result
+ $mappedData[$key] = $value;
+ }
+
+ if (count($gpsData) === 2) {
+ $gpsLocation = sprintf(
+ '%s,%s',
+ (strtoupper($data['GPSLatitudeRef'][0]) === 'S' ? -1 : 1) * $gpsData['lat'],
+ (strtoupper($data['GPSLongitudeRef'][0]) === 'W' ? -1 : 1) * $gpsData['lon']
+ );
+ $mappedData[Exif::GPS] = $gpsLocation;
+ }
+
+ return $mappedData;
+ }
+
+ /**
+ * Determines if given field is a section
+ *
+ * @param string $field
+ * @return bool
+ */
+ protected function isSection($field)
+ {
+ return (in_array($field, $this->sections));
+ }
+
+ /**
+ * Extract GPS coordinates from components array
+ *
+ * @param array $components
+ * @return float
+ */
+ protected function extractGPSCoordinate(array $components)
+ {
+ $components = array_map(array($this, '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/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);
}
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
{
/**
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
diff --git a/tests/PHPExif/Adapter/AdapterAbstractTest.php b/tests/PHPExif/Adapter/AdapterAbstractTest.php
index 97d2794..46982da 100644
--- a/tests/PHPExif/Adapter/AdapterAbstractTest.php
+++ b/tests/PHPExif/Adapter/AdapterAbstractTest.php
@@ -1,5 +1,8 @@
+ * @covers \PHPExif\Adapter\AdapterInterface
+ */
class AdapterAbstractTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -14,161 +17,216 @@ public function setUp()
/**
* @group adapter
- * @covers \PHPExif\Adapter\AdapterAbstract::determinePropertyGetter
+ * @covers \PHPExif\Adapter\AdapterAbstract::setOptions
*/
- public function testDeterminePropertyGetter()
+ public function testSetOptionsReturnsCurrentInstance()
{
- $reflMethod = new \ReflectionMethod('\PHPExif\Adapter\Native', 'determinePropertyGetter');
- $reflMethod->setAccessible(true);
+ $result = $this->adapter->setOptions(array());
+ $this->assertSame($this->adapter, $result);
+ }
- $result = $reflMethod->invoke(
- $this->adapter,
- 'foo'
+ /**
+ * @group adapter
+ * @covers \PHPExif\Adapter\AdapterAbstract::setOptions
+ */
+ public function testSetOptionsCorrectlySetsProperties()
+ {
+ $expected = array(
+ 'requiredSections' => array('foo', 'bar', 'baz',),
+ 'includeThumbnail' => \PHPExif\Adapter\Native::INCLUDE_THUMBNAIL,
+ 'sectionsAsArrays' => \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS,
);
+ $this->adapter->setOptions($expected);
- $this->assertEquals('getFoo', $result);
+ foreach ($expected as $key => $value) {
+ $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key);
+ $reflProp->setAccessible(true);
+ $this->assertEquals($value, $reflProp->getValue($this->adapter));
+ }
}
/**
* @group adapter
- * @covers \PHPExif\Adapter\AdapterAbstract::determinePropertySetter
+ * @covers \PHPExif\Adapter\AdapterAbstract::setOptions
*/
- public function testDeterminePropertySetter()
+ public function testSetOptionsIgnoresPropertiesWithoutSetters()
{
- $reflMethod = new \ReflectionMethod('\PHPExif\Adapter\Native', 'determinePropertySetter');
- $reflMethod->setAccessible(true);
+ $expected = array(
+ 'iptcMapping' => array('foo', 'bar', 'baz'),
+ );
+ $this->adapter->setOptions($expected);
+
+ foreach ($expected as $key => $value) {
+ $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key);
+ $reflProp->setAccessible(true);
+ $this->assertNotEquals($value, $reflProp->getValue($this->adapter));
+ }
+ }
+
- $result = $reflMethod->invoke(
- $this->adapter,
- 'foo'
+ /**
+ * @group adapter
+ * @covers \PHPExif\Adapter\AdapterAbstract::__construct
+ */
+ public function testConstructorSetsOptions()
+ {
+ $expected = array(
+ 'requiredSections' => array('foo', 'bar', 'baz',),
+ 'includeThumbnail' => \PHPExif\Adapter\Native::INCLUDE_THUMBNAIL,
+ 'sectionsAsArrays' => \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS,
);
+ $adapter = new \PHPExif\Adapter\Native($expected);
- $this->assertEquals('setFoo', $result);
+ foreach ($expected as $key => $value) {
+ $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\Native', $key);
+ $reflProp->setAccessible(true);
+ $this->assertEquals($value, $reflProp->getValue($adapter));
+ }
}
/**
* @group adapter
- * @covers \PHPExif\Adapter\AdapterAbstract::getClassConstantsOfType
+ * @covers \PHPExif\Adapter\AdapterAbstract::setMapper
*/
- public function testGetClassConstantsOfTypeAlwaysReturnsArray()
+ public function testSetMapperReturnsCurrentInstance()
{
- $result = $this->adapter->getClassConstantsOfType('sections');
- $this->assertInternalType('array', $result);
- $result = $this->adapter->getClassConstantsOfType('foo');
- $this->assertInternalType('array', $result);
+ $mapper = new \PHPExif\Mapper\Native();
+ $result = $this->adapter->setMapper($mapper);
+ $this->assertSame($this->adapter, $result);
}
/**
* @group adapter
- * @covers \PHPExif\Adapter\AdapterAbstract::getClassConstantsOfType
+ * @covers \PHPExif\Adapter\AdapterAbstract::setMapper
*/
- public function testGetClassConstantsOfTypeReturnsCorrectData()
+ public function testSetMapperCorrectlySetsInProperty()
{
- $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);
+ $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::toArray
+ * @covers \PHPExif\Adapter\AdapterAbstract::getMapper
*/
- public function testToArrayReturnsPropertiesWithGetters()
+ public function testGetMapperCorrectlyReturnsFromProperty()
{
- $expected = array(
- 'requiredSections',
- 'includeThumbnail',
- 'sectionsAsArrays',
+ $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'
);
- $result = $this->adapter->toArray();
- $actual = array_keys($result);
- $this->assertEquals($expected, $actual);
+
+ $mapperClass = '\\PHPExif\\Mapper\\Native';
+ $reflProp->setAccessible(true);
+ $reflProp->setValue($this->adapter, $mapperClass);
+
+ $this->assertInstanceOf($mapperClass, $this->adapter->getMapper());
}
/**
* @group adapter
- * @covers \PHPExif\Adapter\AdapterAbstract::toArray
+ * @covers \PHPExif\Adapter\AdapterAbstract::getMapper
*/
- public function testToArrayOmmitsPropertiesWithoutGetters()
+ public function testGetMapperLazyLoadingSetsInProperty()
{
- $expected = array(
- 'iptcMapping',
+ $reflProp = new \ReflectionProperty(
+ get_class($this->adapter),
+ 'mapperClass'
);
- $result = $this->adapter->toArray();
- $actual = array_keys($result);
- $diff = array_diff($expected, $actual);
- $this->assertEquals($expected, $diff);
+
+ $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::setOptions
+ * @covers \PHPExif\Adapter\AdapterAbstract::setHydrator
*/
- public function testSetOptionsReturnsCurrentInstance()
+ public function testSetHydratorReturnsCurrentInstance()
{
- $result = $this->adapter->setOptions(array());
+ $hydrator = new \PHPExif\Hydrator\Mutator();
+ $result = $this->adapter->setHydrator($hydrator);
$this->assertSame($this->adapter, $result);
}
/**
* @group adapter
- * @covers \PHPExif\Adapter\AdapterAbstract::setOptions
+ * @covers \PHPExif\Adapter\AdapterAbstract::setHydrator
*/
- public function testSetOptionsCorrectlySetsProperties()
+ public function testSetHydratorCorrectlySetsInProperty()
{
- $expected = array(
- 'requiredSections' => array('foo', 'bar', 'baz',),
- 'includeThumbnail' => \PHPExif\Adapter\Native::INCLUDE_THUMBNAIL,
- 'sectionsAsArrays' => \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS,
- );
- $this->adapter->setOptions($expected);
+ $hydrator = new \PHPExif\Hydrator\Mutator();
+ $this->adapter->setHydrator($hydrator);
- foreach ($expected as $key => $value) {
- $reflProp = new \ReflectionProperty('\PHPExif\Adapter\Native', $key);
- $reflProp->setAccessible(true);
- $this->assertEquals($value, $reflProp->getValue($this->adapter));
- }
+ $reflProp = new \ReflectionProperty('\\PHPExif\\Adapter\\AdapterAbstract', 'hydrator');
+ $reflProp->setAccessible(true);
+ $this->assertSame($hydrator, $reflProp->getValue($this->adapter));
}
/**
* @group adapter
- * @covers \PHPExif\Adapter\AdapterAbstract::setOptions
+ * @covers \PHPExif\Adapter\AdapterAbstract::getHydrator
*/
- public function testSetOptionsIgnoresPropertiesWithoutSetters()
+ public function testGetHydratorCorrectlyReturnsFromProperty()
{
- $expected = array(
- 'iptcMapping' => array('foo', 'bar', 'baz'),
- );
- $this->adapter->setOptions($expected);
-
- foreach ($expected as $key => $value) {
- $reflProp = new \ReflectionProperty('\PHPExif\Adapter\Native', $key);
- $reflProp->setAccessible(true);
- $this->assertNotEquals($value, $reflProp->getValue($this->adapter));
- }
+ $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::__construct
+ * @covers \PHPExif\Adapter\AdapterAbstract::getHydrator
*/
- public function testConstructorSetsOptions()
+ public function testGetHydratorLazyLoadingSetsInProperty()
{
- $expected = array(
- 'requiredSections' => array('foo', 'bar', 'baz',),
- 'includeThumbnail' => \PHPExif\Adapter\Native::INCLUDE_THUMBNAIL,
- 'sectionsAsArrays' => \PHPExif\Adapter\Native::SECTIONS_AS_ARRAYS,
- );
- $adapter = new \PHPExif\Adapter\Native($expected);
+ $hydratorClass = '\\PHPExif\\Hydrator\\Mutator';
- foreach ($expected as $key => $value) {
- $reflProp = new \ReflectionProperty('\PHPExif\Adapter\Native', $key);
- $reflProp->setAccessible(true);
- $this->assertEquals($value, $reflProp->getValue($adapter));
- }
+ $reflProp = new \ReflectionProperty(
+ get_class($this->adapter),
+ 'hydrator'
+ );
+ $reflProp->setAccessible(true);
+ $this->adapter->getHydrator();
+ $this->assertInstanceOf($hydratorClass, $reflProp->getValue($this->adapter));
}
}
+
diff --git a/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php b/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php
new file mode 100644
index 0000000..9d9bd39
--- /dev/null
+++ b/tests/PHPExif/Adapter/ExiftoolProcOpenTest.php
@@ -0,0 +1,68 @@
+
+ */
+ class ExiftoolProcOpenTest extends \PHPUnit_Framework_TestCase
+ {
+ /**
+ * @var \PHPExif\Adapter\Exiftool
+ */
+ protected $adapter;
+
+ public function setUp()
+ {
+ global $mockProcOpen;
+ $mockProcOpen = true;
+ $this->adapter = new \PHPExif\Adapter\Exiftool();
+ }
+
+ public function tearDown()
+ {
+ global $mockProcOpen;
+ $mockProcOpen = false;
+ }
+
+ /**
+ * @group exiftool
+ * @covers \PHPExif\Adapter\Exiftool::getCliOutput
+ * @expectedException RuntimeException
+ */
+ public function testGetCliOutput()
+ {
+ $reflMethod = new \ReflectionMethod('\PHPExif\Adapter\Exiftool', 'getCliOutput');
+ $reflMethod->setAccessible(true);
+
+ $result = $reflMethod->invoke(
+ $this->adapter,
+ sprintf(
+ '%1$s',
+ 'pwd'
+ )
+ );
+ }
+ }
+}
diff --git a/tests/PHPExif/Adapter/ExiftoolTest.php b/tests/PHPExif/Adapter/ExiftoolTest.php
index 5e8783b..71abd2a 100644
--- a/tests/PHPExif/Adapter/ExiftoolTest.php
+++ b/tests/PHPExif/Adapter/ExiftoolTest.php
@@ -1,4 +1,7 @@
+ */
class ExiftoolTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -60,114 +63,32 @@ public function testGetToolPathLazyLoadsPath()
$this->assertInternalType('string', $this->adapter->getToolPath());
}
- /**
- * @group exiftool
- * @covers \PHPExif\Adapter\Exiftool::getExifFromFile
- */
- public function testGetExifFromFile()
- {
- $file = PHPEXIF_TEST_ROOT . '/files/morning_glory_pool_500.jpg';
- $result = $this->adapter->getExifFromFile($file);
- $this->assertInstanceOf('\PHPExif\Exif', $result);
- $this->assertInternalType('array', $result->getRawData());
- $this->assertNotEmpty($result->getRawData());
- }
-
- /**
- * @group exiftool
- * @covers \PHPExif\Adapter\Exiftool::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()
+ public function testSetNumericInProperty()
{
- $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',
- )
- );
+ $reflProperty = new \ReflectionProperty('\PHPExif\Adapter\Exiftool', 'numeric');
+ $reflProperty->setAccessible(true);
- $expected = '40.333452380556,-20.167314813889';
- $this->assertEquals($expected, $result[\PHPExif\Exif::GPS]);
+ $expected = true;
+ $this->adapter->setNumeric($expected);
+
+ $this->assertEquals($expected, $reflProperty->getValue($this->adapter));
}
/**
* @group exiftool
- * @covers \PHPExif\Adapter\Exiftool::mapData
- * @covers \PHPExif\Adapter\Exiftool::extractGPSCoordinates
+ * @covers \PHPExif\Adapter\Exiftool::getExifFromFile
*/
- public function testMapDataCreationNumericGPSIsCalculated()
+ public function testGetExifFromFile()
{
- $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]);
+ $file = PHPEXIF_TEST_ROOT . '/files/morning_glory_pool_500.jpg';
+ $result = $this->adapter->getExifFromFile($file);
+ $this->assertInstanceOf('\PHPExif\Exif', $result);
+ $this->assertInternalType('array', $result->getRawData());
+ $this->assertNotEmpty($result->getRawData());
}
/**
diff --git a/tests/PHPExif/Adapter/NativeTest.php b/tests/PHPExif/Adapter/NativeTest.php
index 381f506..7dd86b6 100755
--- a/tests/PHPExif/Adapter/NativeTest.php
+++ b/tests/PHPExif/Adapter/NativeTest.php
@@ -1,4 +1,7 @@
+ */
class NativeTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -179,165 +182,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]);
- }
}
diff --git a/tests/PHPExif/ExifTest.php b/tests/PHPExif/ExifTest.php
index 8f51f21..964a917 100755
--- a/tests/PHPExif/ExifTest.php
+++ b/tests/PHPExif/ExifTest.php
@@ -1,5 +1,7 @@
+ */
class ExifTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -17,6 +19,7 @@ public function setUp()
/**
* @group exif
+ * @covers \PHPExif\Exif::__construct
*/
public function testConstructorCallsSetData()
{
@@ -42,6 +45,7 @@ public function testConstructorCallsSetData()
/**
* @group exif
+ * @covers \PHPExif\Exif::getRawData
*/
public function testGetRawData()
{
@@ -53,6 +57,7 @@ public function testGetRawData()
/**
* @group exif
+ * @covers \PHPExif\Exif::setRawData
*/
public function testSetRawData()
{
@@ -68,6 +73,7 @@ public function testSetRawData()
/**
* @group exif
+ * @covers \PHPExif\Exif::getData
*/
public function testGetData()
{
@@ -79,6 +85,7 @@ public function testGetData()
/**
* @group exif
+ * @covers \PHPExif\Exif::setData
*/
public function testSetData()
{
@@ -95,6 +102,33 @@ 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
+ * @covers \PHPExif\Exif::getHeadline
+ * @covers \PHPExif\Exif::getColorSpace
+ * @covers \PHPExif\Exif::getOrientation
+ * @covers \PHPExif\Exif::getGPS
* @param string $accessor
*/
public function testUndefinedPropertiesReturnFalse($accessor)
@@ -133,6 +167,12 @@ public function providerUndefinedPropertiesReturnFalse()
array('getCredit'),
array('getSource'),
array('getJobtitle'),
+ array('getMimeType'),
+ array('getFileSize'),
+ array('getHeadline'),
+ array('getColorSpace'),
+ array('getOrientation'),
+ array('getGPS'),
);
}
@@ -438,6 +478,10 @@ public function testGetFileSize()
$this->assertEquals($expected, $this->exif->getFileSize());
}
+ /**
+ * @group exif
+ * @covers \PHPExif\Exif::getOrientation
+ */
public function testGetOrientation()
{
$expected = 1;
@@ -458,8 +502,99 @@ 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::setFocusDistance
+ * @covers \PHPExif\Exif::setWidth
+ * @covers \PHPExif\Exif::setHeight
+ * @covers \PHPExif\Exif::setTitle
+ * @covers \PHPExif\Exif::setCaption
+ * @covers \PHPExif\Exif::setCopyright
+ * @covers \PHPExif\Exif::setKeywords
+ * @covers \PHPExif\Exif::setCamera
+ * @covers \PHPExif\Exif::setHorizontalResolution
+ * @covers \PHPExif\Exif::setVerticalResolution
+ * @covers \PHPExif\Exif::setSoftware
+ * @covers \PHPExif\Exif::setFocalLength
+ * @covers \PHPExif\Exif::setCreationDate
+ * @covers \PHPExif\Exif::setAuthor
+ * @covers \PHPExif\Exif::setCredit
+ * @covers \PHPExif\Exif::setSource
+ * @covers \PHPExif\Exif::setJobtitle
+ * @covers \PHPExif\Exif::setMimeType
+ * @covers \PHPExif\Exif::setFileSize
+ * @covers \PHPExif\Exif::setHeadline
+ * @covers \PHPExif\Exif::setColorSpace
+ * @covers \PHPExif\Exif::setOrientation
+ * @covers \PHPExif\Exif::setGPS
+ */
+ public function testMutatorMethodsSetInProperty()
+ {
+ $reflClass = new \ReflectionClass(get_class($this->exif));
+ $constants = $reflClass->getConstants();
+
+ $reflProp = new \ReflectionProperty(get_class($this->exif), 'data');
+ $reflProp->setAccessible(true);
+
+ $expected = 'foo';
+ foreach ($constants as $name => $value) {
+ $setter = 'set' . ucfirst($value);
+
+ switch ($value) {
+ case 'creationdate':
+ $now = new \DateTime();
+ $this->exif->$setter($now);
+ $propertyValue = $reflProp->getValue($this->exif);
+ $this->assertSame($now, $propertyValue[$value]);
+ break;
+ case 'gps':
+ $coords = '40.333452380556,-20.167314813889';
+ $setter = 'setGPS';
+ $this->exif->$setter($coords);
+ $propertyValue = $reflProp->getValue($this->exif);
+ $this->assertEquals($coords, $propertyValue[$value]);
+ break;
+ case 'focalDistance':
+ $setter = 'setFocusDistance';
+ default:
+ $this->exif->$setter($expected);
+ $propertyValue = $reflProp->getValue($this->exif);
+ $this->assertEquals($expected, $propertyValue[$value]);
+ break;
+ }
+ }
+ }
+
/**
* Test that the values returned by both adapters are equal
+ *
+ * @group consistency
+ * @covers \PHPExif\Exif::getAperture
+ * @covers \PHPExif\Exif::getIso
+ * @covers \PHPExif\Exif::getExposure
+ * @covers \PHPExif\Exif::getExposureMilliseconds
+ * @covers \PHPExif\Exif::getFocusDistance
+ * @covers \PHPExif\Exif::getWidth
+ * @covers \PHPExif\Exif::getHeight
+ * @covers \PHPExif\Exif::getTitle
+ * @covers \PHPExif\Exif::getCaption
+ * @covers \PHPExif\Exif::getCopyright
+ * @covers \PHPExif\Exif::getKeywords
+ * @covers \PHPExif\Exif::getCamera
+ * @covers \PHPExif\Exif::getHorizontalResolution
+ * @covers \PHPExif\Exif::getVerticalResolution
+ * @covers \PHPExif\Exif::getSoftware
+ * @covers \PHPExif\Exif::getFocalLength
+ * @covers \PHPExif\Exif::getCreationDate
+ * @covers \PHPExif\Exif::getAuthor
+ * @covers \PHPExif\Exif::getCredit
+ * @covers \PHPExif\Exif::getSource
+ * @covers \PHPExif\Exif::getJobtitle
+ * @covers \PHPExif\Exif::getMimeType
+ * @covers \PHPExif\Exif::getFileSize
*/
public function testAdapterConsistency()
{
@@ -480,7 +615,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(
@@ -492,3 +627,4 @@ public function testAdapterConsistency()
}
}
}
+
diff --git a/tests/PHPExif/Hydrator/MutatorTest.php b/tests/PHPExif/Hydrator/MutatorTest.php
new file mode 100644
index 0000000..280188b
--- /dev/null
+++ b/tests/PHPExif/Hydrator/MutatorTest.php
@@ -0,0 +1,69 @@
+
+ * @covers \PHPExif\Hydrator\HydratorInterface
+ */
+class MutatorTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * Setup function before the tests
+ */
+ public function setUp()
+ {
+ }
+
+ /**
+ * @group hydrator
+ * @covers \PHPExif\Hydrator\Mutator::hydrate
+ */
+ public function testHydrateCallsDetermineMutator()
+ {
+ // input data
+ $input = array(
+ 'foo' => 'bar',
+ );
+
+ // create mock
+ $mock = $this->getMock('\\PHPExif\\Hydrator\\Mutator', array('determineMutator'));
+
+ $mock->expects($this->exactly(count($input)))
+ ->method('determineMutator')
+ ->will($this->returnValue('setFoo'));
+
+ $object = new TestClass();
+
+ // do the test
+ $mock->hydrate($object, $input);
+ }
+
+ /**
+ * @group hydrator
+ * @covers \PHPExif\Hydrator\Mutator::hydrate
+ */
+ public function testHydrateCallsMutatorsOnObject()
+ {
+ // input data
+ $input = array(
+ 'bar' => 'baz',
+ );
+
+ // create mock
+ $mock = $this->getMock('TestClass', array('setBar'));
+
+ $mock->expects($this->once())
+ ->method('setBar')
+ ->with($this->equalTo($input['bar']));
+
+ // do the test
+ $hydrator = new \PHPExif\Hydrator\Mutator;
+ $hydrator->hydrate($mock, $input);
+ }
+}
+
+class TestClass
+{
+ public function setBar()
+ {
+ }
+}
+
diff --git a/tests/PHPExif/Mapper/ExiftoolMapperTest.php b/tests/PHPExif/Mapper/ExiftoolMapperTest.php
new file mode 100644
index 0000000..485cda8
--- /dev/null
+++ b/tests/PHPExif/Mapper/ExiftoolMapperTest.php
@@ -0,0 +1,239 @@
+
+ */
+class ExiftoolMapperTest extends \PHPUnit_Framework_TestCase
+{
+ protected $mapper;
+
+ public function setUp()
+ {
+ $this->mapper = new \PHPExif\Mapper\Exiftool;
+ }
+
+ /**
+ * @group mapper
+ */
+ public function testClassImplementsCorrectInterface()
+ {
+ $this->assertInstanceOf('\\PHPExif\\Mapper\\MapperInterface', $this->mapper);
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Exiftool::mapRawData
+ */
+ public function testMapRawDataIgnoresFieldIfItDoesntExist()
+ {
+ $rawData = array('foo' => 'bar');
+ $mapped = $this->mapper->mapRawData($rawData);
+
+ $this->assertCount(0, $mapped);
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Exiftool::mapRawData
+ */
+ public function testMapRawDataMapsFieldsCorrectly()
+ {
+ $reflProp = new \ReflectionProperty(get_class($this->mapper), 'map');
+ $reflProp->setAccessible(true);
+ $map = $reflProp->getValue($this->mapper);
+
+ // ignore custom formatted data stuff:
+ unset($map[\PHPExif\Mapper\Exiftool::APERTURE]);
+ unset($map[\PHPExif\Mapper\Exiftool::APPROXIMATEFOCUSDISTANCE]);
+ unset($map[\PHPExif\Mapper\Exiftool::CREATEDATE]);
+ unset($map[\PHPExif\Mapper\Exiftool::EXPOSURETIME]);
+ unset($map[\PHPExif\Mapper\Exiftool::FOCALLENGTH]);
+ unset($map[\PHPExif\Mapper\Exiftool::GPSLATITUDE]);
+ unset($map[\PHPExif\Mapper\Exiftool::GPSLONGITUDE]);
+
+ // create raw data
+ $keys = array_keys($map);
+ $values = array();
+ $values = array_pad($values, count($keys), 'foo');
+ $rawData = array_combine($keys, $values);
+
+
+ $mapped = $this->mapper->mapRawData($rawData);
+
+ $i = 0;
+ foreach ($mapped as $key => $value) {
+ $this->assertEquals($map[$keys[$i]], $key);
+ $i++;
+ }
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Exiftool::mapRawData
+ */
+ public function testMapRawDataCorrectlyFormatsAperture()
+ {
+ $rawData = array(
+ \PHPExif\Mapper\Exiftool::APERTURE => 0.123,
+ );
+
+ $mapped = $this->mapper->mapRawData($rawData);
+
+ $this->assertEquals('f/0.1', reset($mapped));
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Exiftool::mapRawData
+ */
+ public function testMapRawDataCorrectlyFormatsFocusDistance()
+ {
+ $rawData = array(
+ \PHPExif\Mapper\Exiftool::APPROXIMATEFOCUSDISTANCE => 50,
+ );
+
+ $mapped = $this->mapper->mapRawData($rawData);
+
+ $this->assertEquals('50m', reset($mapped));
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Exiftool::mapRawData
+ */
+ public function testMapRawDataCorrectlyFormatsCreationDate()
+ {
+ $rawData = array(
+ \PHPExif\Mapper\Exiftool::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));
+ }
+
+ /**
+ * @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));
+ }
+
+ /**
+ * @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));
+ }
+}
diff --git a/tests/PHPExif/Mapper/NativeMapperTest.php b/tests/PHPExif/Mapper/NativeMapperTest.php
new file mode 100644
index 0000000..d6e78fc
--- /dev/null
+++ b/tests/PHPExif/Mapper/NativeMapperTest.php
@@ -0,0 +1,190 @@
+
+ */
+class NativeMapperTest extends \PHPUnit_Framework_TestCase
+{
+ protected $mapper;
+
+ public function setUp()
+ {
+ $this->mapper = new \PHPExif\Mapper\Native;
+ }
+
+ /**
+ * @group mapper
+ */
+ public function testClassImplementsCorrectInterface()
+ {
+ $this->assertInstanceOf('\\PHPExif\\Mapper\\MapperInterface', $this->mapper);
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Native::mapRawData
+ */
+ public function testMapRawDataIgnoresFieldIfItDoesntExist()
+ {
+ $rawData = array('foo' => 'bar');
+ $mapped = $this->mapper->mapRawData($rawData);
+
+ $this->assertCount(0, $mapped);
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Native::mapRawData
+ */
+ public function testMapRawDataMapsFieldsCorrectly()
+ {
+ $reflProp = new \ReflectionProperty(get_class($this->mapper), 'map');
+ $reflProp->setAccessible(true);
+ $map = $reflProp->getValue($this->mapper);
+
+ // ignore custom formatted data stuff:
+ unset($map[\PHPExif\Mapper\Native::DATETIMEORIGINAL]);
+ unset($map[\PHPExif\Mapper\Native::EXPOSURETIME]);
+ unset($map[\PHPExif\Mapper\Native::FOCALLENGTH]);
+ unset($map[\PHPExif\Mapper\Native::XRESOLUTION]);
+ unset($map[\PHPExif\Mapper\Native::YRESOLUTION]);
+ unset($map[\PHPExif\Mapper\Native::GPSLATITUDE]);
+ unset($map[\PHPExif\Mapper\Native::GPSLONGITUDE]);
+
+ // create raw data
+ $keys = array_keys($map);
+ $values = array();
+ $values = array_pad($values, count($keys), 'foo');
+ $rawData = array_combine($keys, $values);
+
+
+ $mapped = $this->mapper->mapRawData($rawData);
+
+ $i = 0;
+ foreach ($mapped as $key => $value) {
+ $this->assertEquals($map[$keys[$i]], $key);
+ $i++;
+ }
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Native::mapRawData
+ */
+ public function testMapRawDataCorrectlyFormatsDateTimeOriginal()
+ {
+ $rawData = array(
+ \PHPExif\Mapper\Native::DATETIMEORIGINAL => '2015:04:01 12:11:09',
+ );
+
+ $mapped = $this->mapper->mapRawData($rawData);
+
+ $result = reset($mapped);
+ $this->assertInstanceOf('\\DateTime', $result);
+ $this->assertEquals(
+ reset($rawData),
+ $result->format('Y:m:d H:i:s')
+ );
+ }
+
+ /**
+ * @group mapper
+ * @covers \PHPExif\Mapper\Native::mapRawData
+ */
+ public function 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);
+ }
+
+ /**
+ * @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));
+ }
+}
diff --git a/tests/PHPExif/Reader/ReaderTest.php b/tests/PHPExif/Reader/ReaderTest.php
index af546c4..82aa133 100644
--- a/tests/PHPExif/Reader/ReaderTest.php
+++ b/tests/PHPExif/Reader/ReaderTest.php
@@ -1,4 +1,9 @@
+ * @covers \PHPExif\Reader\ReaderInterface
+ * @covers \PHPExif\Adapter\NoAdapterException
+ */
class ReaderTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -45,6 +50,21 @@ public function testGetAdapterFromProperty()
$this->assertSame($mock, $this->reader->getAdapter());
}
+ /**
+ * @group reader
+ * @covers \PHPExif\Reader\Reader::getAdapter
+ * @covers \PHPExif\Adapter\NoAdapterException
+ * @expectedException \PHPExif\Adapter\NoAdapterException
+ */
+ public function testGetAdapterThrowsExceptionWhenNoAdapterIsSet()
+ {
+ $reflProperty = new \ReflectionProperty('\PHPExif\Reader\Reader', 'adapter');
+ $reflProperty->setAccessible(true);
+ $reflProperty->setValue($this->reader, null);
+
+ $this->reader->getAdapter();
+ }
+
/**
* @group reader
* @covers \PHPExif\Reader\Reader::read
@@ -112,4 +132,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);
+ }
}
+