diff --git a/src/Geocoder/Exception/ChainNoResultException.php b/src/Geocoder/Exception/ChainNoResultException.php new file mode 100644 index 000000000..c4475d227 --- /dev/null +++ b/src/Geocoder/Exception/ChainNoResultException.php @@ -0,0 +1,46 @@ + + */ +class ChainNoResultException extends NoResultException +{ + + /** + * Exceptions from chained providers + * + * @var array + */ + private $exceptions = array(); + + /** + * Constructor + * + * @param string $message + * @param array $exceptions Array of Exception instances + */ + public function __construct($message = "", array $exceptions = array()) + { + parent::__construct($message); + $this->exceptions = $exceptions; + } + + /** + * Get the exceptions from chained providers + */ + public function getExceptions() + { + return $this->exceptions; + } + +} diff --git a/src/Geocoder/Provider/ChainProvider.php b/src/Geocoder/Provider/ChainProvider.php index 616d6a84b..ced54c3df 100644 --- a/src/Geocoder/Provider/ChainProvider.php +++ b/src/Geocoder/Provider/ChainProvider.php @@ -10,8 +10,8 @@ namespace Geocoder\Provider; -use Geocoder\Exception\NoResultException; use Geocoder\Exception\InvalidCredentialsException; +use Geocoder\Exception\ChainNoResultException; /** * @author Markus Bachmann @@ -48,16 +48,19 @@ public function addProvider(ProviderInterface $provider) */ public function getGeocodedData($address) { + $exceptions = array(); + foreach ($this->providers as $provider) { try { return $provider->getGeocodedData($address); } catch (InvalidCredentialsException $e) { throw $e; } catch (\Exception $e) { + $exceptions[] = $e; } } - throw new NoResultException(sprintf('No provider could provide the address "%s"', $address)); + throw new ChainNoResultException(sprintf('No provider could provide the address "%s"', $address), $exceptions); } /** @@ -65,16 +68,19 @@ public function getGeocodedData($address) */ public function getReversedData(array $coordinates) { + $exceptions = array(); + foreach ($this->providers as $provider) { try { return $provider->getReversedData($coordinates); } catch (InvalidCredentialsException $e) { throw $e; } catch (\Exception $e) { + $exceptions[] = $e; } } - throw new NoResultException(sprintf('No provider could provide the coordinated %s', json_encode($coordinates))); + throw new ChainNoResultException(sprintf('No provider could provide the coordinated %s', json_encode($coordinates)), $exceptions); } /** diff --git a/tests/Geocoder/Tests/Provider/ChainProviderTest.php b/tests/Geocoder/Tests/Provider/ChainProviderTest.php index 24152a91b..e67ca49d4 100644 --- a/tests/Geocoder/Tests/Provider/ChainProviderTest.php +++ b/tests/Geocoder/Tests/Provider/ChainProviderTest.php @@ -4,6 +4,7 @@ use Geocoder\Tests\TestCase; use Geocoder\Provider\ChainProvider; +use Geocoder\Exception\ChainNoResultException; /** * @author Markus Bachmann @@ -42,6 +43,22 @@ public function testGetReversedData() $this->assertEquals(array('foo' => 'bar'), $chain->getReversedData(array('11', '22'))); } + public function testChainProviderReverseThrowsChainNoResultException() + { + $mockOne = $this->getMock('Geocoder\\Provider\\ProviderInterface'); + $mockOne->expects($this->exactly(2)) + ->method('getReversedData') + ->will($this->returnCallback(function() { throw new \Exception; })); + + $chain = new ChainProvider(array($mockOne, $mockOne)); + + try { + $chain->getReversedData(array('11', '22')); + } catch (ChainNoResultException $e) { + $this->assertCount(2, $e->getExceptions()); + } + } + public function testGetGeocodedData() { $mockOne = $this->getMock('Geocoder\\Provider\\ProviderInterface'); @@ -59,4 +76,20 @@ public function testGetGeocodedData() $this->assertEquals(array('foo' => 'bar'), $chain->getGeocodedData('Paris')); } + + public function testChainProviderGeocodeThrowsChainNoResultException() + { + $mockOne = $this->getMock('Geocoder\\Provider\\ProviderInterface'); + $mockOne->expects($this->exactly(2)) + ->method('getGeocodedData') + ->will($this->returnCallback(function() { throw new \Exception; })); + + $chain = new ChainProvider(array($mockOne, $mockOne)); + + try { + $chain->getGeocodedData('Paris'); + } catch (ChainNoResultException $e) { + $this->assertCount(2, $e->getExceptions()); + } + } }