diff --git a/.travis.yml b/.travis.yml index 006296b..b860f65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,12 @@ php: - 5.4 - 5.5 -script: phpunit +before_install: + - pear install pear/PHP_CodeSniffer + +script: + - phpcs --standard=PSR2 src/ + - phpunit notifications: email: diff --git a/README b/README index 69c53bd..4332b48 100644 --- a/README +++ b/README @@ -58,6 +58,10 @@ SUPPORT to the client API please see http://www.maxmind.com/en/support for details. +CONTRIBUTING + Patches and pull requests are encouraged. All code should follow the + PSR-2 style guidelines. Please include unit tests whenever possible. + AUTHOR Gregory Oschwald diff --git a/src/GeoIP2/Exception/HttpException.php b/src/GeoIP2/Exception/HttpException.php index 000c22a..4b5ef85 100644 --- a/src/GeoIP2/Exception/HttpException.php +++ b/src/GeoIP2/Exception/HttpException.php @@ -4,13 +4,15 @@ namespace GeoIP2\Exception; class HttpException extends \Exception { - public $code; + public $code; - public function __construct($message, $code, $uri, - Exception $previous = null) - { - $this->code = $code; - parent::__construct($message, null, $previous); - } - -} \ No newline at end of file + public function __construct( + $message, + $code, + $uri, + Exception $previous = null + ) { + $this->code = $code; + parent::__construct($message, null, $previous); + } +} diff --git a/src/GeoIP2/Exception/WebserviceException.php b/src/GeoIP2/Exception/WebserviceException.php index c422110..fc46e31 100644 --- a/src/GeoIP2/Exception/WebserviceException.php +++ b/src/GeoIP2/Exception/WebserviceException.php @@ -4,13 +4,16 @@ namespace GeoIP2\Exception; class WebserviceException extends HttpException { - public $httpStatus; + public $httpStatus; - public function __construct($message, $code, $httpStatus, $uri, - Exception $previous = null) - { - $this->httpStatus = $httpStatus; - parent::__construct($message, $code, $uri, $previous); - } - -} \ No newline at end of file + public function __construct( + $message, + $code, + $httpStatus, + $uri, + Exception $previous = null + ) { + $this->httpStatus = $httpStatus; + parent::__construct($message, $code, $uri, $previous); + } +} diff --git a/src/GeoIP2/Model/City.php b/src/GeoIP2/Model/City.php index cc7f236..9f09b96 100644 --- a/src/GeoIP2/Model/City.php +++ b/src/GeoIP2/Model/City.php @@ -4,28 +4,49 @@ namespace GeoIP2\Model; class City extends Country { - protected $city; - protected $location; - protected $postal; - protected $subdivisions = Array(); + protected $city; + protected $location; + protected $postal; + protected $subdivisions = array(); - public function __construct($raw, $languages) - { - parent::__construct($raw, $languages); + public function __construct($raw, $languages) + { + parent::__construct($raw, $languages); - $this->city = new \GeoIP2\Record\City($this->get('city'), $languages); - $this->location = new \GeoIP2\Record\Location($this->get('location')); - $this->postal = new \GeoIP2\Record\Postal($this->get('postal')); + $this->city = new \GeoIP2\Record\City($this->get('city'), $languages); + $this->location = new \GeoIP2\Record\Location($this->get('location')); + $this->postal = new \GeoIP2\Record\Postal($this->get('postal')); - $this->createSubdivisions($raw, $languages); - } - - private function createSubdivisions($raw, $languages) { - if(!isset($raw['subdivisions'])) return; - - foreach ($raw['subdivisions'] as $sub) { - array_push($this->subdivisions, - new \GeoIP2\Record\Subdivision($sub, $languages)); + $this->createSubdivisions($raw, $languages); } - } -} \ No newline at end of file + + private function createSubdivisions($raw, $languages) + { + if (!isset($raw['subdivisions'])) { + return; + } + + foreach ($raw['subdivisions'] as $sub) { + array_push( + $this->subdivisions, + new \GeoIP2\Record\Subdivision($sub, $languages) + ); + } + } + + public function __get($attr) + { + if ($attr == 'mostSpecificSubdivision') { + return $this->$attr(); + } else { + return parent::__get($attr); + } + } + + private function mostSpecificSubdivision() + { + return empty($this->subdivisions)? + new \GeoIP2\Record\Subdivision(array(), $this->languages): + end($this->subdivisions); + } +} diff --git a/src/GeoIP2/Model/CityIspOrg.php b/src/GeoIP2/Model/CityIspOrg.php index 0d43417..354d163 100644 --- a/src/GeoIP2/Model/CityIspOrg.php +++ b/src/GeoIP2/Model/CityIspOrg.php @@ -4,5 +4,4 @@ namespace GeoIP2\Model; class CityIspOrg extends City { - -} \ No newline at end of file +} diff --git a/src/GeoIP2/Model/Country.php b/src/GeoIP2/Model/Country.php index 478aa79..9810aa9 100644 --- a/src/GeoIP2/Model/Country.php +++ b/src/GeoIP2/Model/Country.php @@ -4,36 +4,50 @@ namespace GeoIP2\Model; class Country { - private $continent; - private $country; - private $registeredCountry; - private $representedCountry; - private $traits; - private $raw; + private $continent; + private $country; + private $languages; + private $registeredCountry; + private $representedCountry; + private $traits; + private $raw; - public function __construct($raw, $languages) { - $this->raw = $raw; + public function __construct($raw, $languages) + { + $this->raw = $raw; - $this->continent = new \GeoIP2\Record\Continent($this->get('continent'), - $languages); - $this->country = new \GeoIP2\Record\Country($this->get('country'), - $languages); - $this->registeredCountry = - new \GeoIP2\Record\Country($this->get('registered_country'), $languages); - $this->representedCountry = - new \GeoIP2\Record\RepresentedCountry($this->get('represented_country'), - $languages); - $this->traits = new \GeoIP2\Record\Traits($this->get('traits')); - } + $this->continent = new \GeoIP2\Record\Continent( + $this->get('continent'), + $languages + ); + $this->country = new \GeoIP2\Record\Country( + $this->get('country'), + $languages + ); + $this->registeredCountry = new \GeoIP2\Record\Country( + $this->get('registered_country'), + $languages + ); + $this->representedCountry = new \GeoIP2\Record\RepresentedCountry( + $this->get('represented_country'), + $languages + ); + $this->traits = new \GeoIP2\Record\Traits($this->get('traits')); - protected function get($field) { - return isset($this->raw[$field]) ? $this->raw[$field] : Array(); - } + $this->languages = $languages; + } - public function __get ($attr) - { - if ($attr != "instance" && isset($this->$attr)) return $this->$attr; + protected function get($field) + { + return isset($this->raw[$field]) ? $this->raw[$field] : array(); + } - throw new \RuntimeException("Unknown attribute: $attr"); - } + public function __get ($attr) + { + if ($attr != "instance" && isset($this->$attr)) { + return $this->$attr; + } + + throw new \RuntimeException("Unknown attribute: $attr"); + } } diff --git a/src/GeoIP2/Model/Omni.php b/src/GeoIP2/Model/Omni.php index 8c676dd..c791539 100644 --- a/src/GeoIP2/Model/Omni.php +++ b/src/GeoIP2/Model/Omni.php @@ -4,5 +4,4 @@ namespace GeoIP2\Model; class Omni extends CityIspOrg { - } diff --git a/src/GeoIP2/Record/AbstractPlaceRecord.php b/src/GeoIP2/Record/AbstractPlaceRecord.php index 91ac51c..a32c2ca 100644 --- a/src/GeoIP2/Record/AbstractPlaceRecord.php +++ b/src/GeoIP2/Record/AbstractPlaceRecord.php @@ -4,25 +4,29 @@ namespace GeoIP2\Record; abstract class AbstractPlaceRecord extends AbstractRecord { - private $languages; + private $languages; - public function __construct($record, $languages){ - $this->languages = $languages; - parent::__construct($record); - } - - public function __get($attr) { - if ($attr == 'name') { - return $this->name(); - } else { - return parent::__get($attr); + public function __construct($record, $languages) + { + $this->languages = $languages; + parent::__construct($record); } - } - - private function name() { - foreach($this->languages as $language) { - if (isset($this->names[$language])) return $this->names[$language]; + public function __get($attr) + { + if ($attr == 'name') { + return $this->name(); + } else { + return parent::__get($attr); + } } - } -} \ No newline at end of file + + private function name() + { + foreach ($this->languages as $language) { + if (isset($this->names[$language])) { + return $this->names[$language]; + } + } + } +} diff --git a/src/GeoIP2/Record/AbstractRecord.php b/src/GeoIP2/Record/AbstractRecord.php index 75679af..c393867 100644 --- a/src/GeoIP2/Record/AbstractRecord.php +++ b/src/GeoIP2/Record/AbstractRecord.php @@ -4,23 +4,25 @@ namespace GeoIP2\Record; abstract class AbstractRecord { - private $record; + private $record; - public function __construct($record) { - $this->record = $record; - } - - public function __get($attr) { - $valid = in_array($attr, $this->validAttributes); - // XXX - kind of ugly but greatly reduces boilerplate code - $key = strtolower(preg_replace('/([A-Z])/', '_\1', $attr)); - - if ($valid && isset($this->record[$key])){ - return $this->record[$key]; - } elseif ($valid) { - return null; - } else { - throw new \RuntimeException("Unknown attribute: $attr"); + public function __construct($record) + { + $this->record = $record; } - } -} \ No newline at end of file + + public function __get($attr) + { + $valid = in_array($attr, $this->validAttributes); + // XXX - kind of ugly but greatly reduces boilerplate code + $key = strtolower(preg_replace('/([A-Z])/', '_\1', $attr)); + + if ($valid && isset($this->record[$key])) { + return $this->record[$key]; + } elseif ($valid) { + return null; + } else { + throw new \RuntimeException("Unknown attribute: $attr"); + } + } +} diff --git a/src/GeoIP2/Record/City.php b/src/GeoIP2/Record/City.php index 26f9875..6ef2e68 100644 --- a/src/GeoIP2/Record/City.php +++ b/src/GeoIP2/Record/City.php @@ -4,5 +4,5 @@ namespace GeoIP2\Record; class City extends AbstractPlaceRecord { - protected $validAttributes = Array('confidence', 'geonameId', 'names'); -} \ No newline at end of file + protected $validAttributes = array('confidence', 'geonameId', 'names'); +} diff --git a/src/GeoIP2/Record/Continent.php b/src/GeoIP2/Record/Continent.php index e69166f..f68b6c8 100644 --- a/src/GeoIP2/Record/Continent.php +++ b/src/GeoIP2/Record/Continent.php @@ -4,7 +4,9 @@ namespace GeoIP2\Record; class Continent extends AbstractPlaceRecord { - protected $validAttributes = Array('continentCode', - 'geonameId', - 'names'); -} \ No newline at end of file + protected $validAttributes = array( + 'continentCode', + 'geonameId', + 'names' + ); +} diff --git a/src/GeoIP2/Record/Country.php b/src/GeoIP2/Record/Country.php index 424f2ec..2aab579 100644 --- a/src/GeoIP2/Record/Country.php +++ b/src/GeoIP2/Record/Country.php @@ -4,9 +4,10 @@ namespace GeoIP2\Record; class Country extends AbstractPlaceRecord { - - protected $validAttributes = Array('confidence', - 'geonameId', - 'isoCode', - 'names'); -} \ No newline at end of file + protected $validAttributes = array( + 'confidence', + 'geonameId', + 'isoCode', + 'names' + ); +} diff --git a/src/GeoIP2/Record/Location.php b/src/GeoIP2/Record/Location.php index 3f76af7..ae17e43 100644 --- a/src/GeoIP2/Record/Location.php +++ b/src/GeoIP2/Record/Location.php @@ -4,11 +4,13 @@ namespace GeoIP2\Record; class Location extends AbstractRecord { - protected $validAttributes = Array('accuracyRadius', - 'latitude', - 'longitude', - 'metroCode', - 'postalCode', - 'postalConfidence', - 'timeZone'); -} \ No newline at end of file + protected $validAttributes = array( + 'accuracyRadius', + 'latitude', + 'longitude', + 'metroCode', + 'postalCode', + 'postalConfidence', + 'timeZone' + ); +} diff --git a/src/GeoIP2/Record/Postal.php b/src/GeoIP2/Record/Postal.php index bfd9344..66a2ee6 100644 --- a/src/GeoIP2/Record/Postal.php +++ b/src/GeoIP2/Record/Postal.php @@ -4,5 +4,5 @@ namespace GeoIP2\Record; class Postal extends AbstractRecord { - protected $validAttributes = Array('code', 'confidence'); + protected $validAttributes = array('code', 'confidence'); } diff --git a/src/GeoIP2/Record/RepresentedCountry.php b/src/GeoIP2/Record/RepresentedCountry.php index 93d8bef..ddc201e 100644 --- a/src/GeoIP2/Record/RepresentedCountry.php +++ b/src/GeoIP2/Record/RepresentedCountry.php @@ -4,9 +4,11 @@ namespace GeoIP2\Record; class RepresentedCountry extends Country { - protected $validAttributes = Array('confidence', - 'geonameId', - 'isoCode', - 'names', - 'type'); -} \ No newline at end of file + protected $validAttributes = array( + 'confidence', + 'geonameId', + 'isoCode', + 'namespace', + 'type' + ); +} diff --git a/src/GeoIP2/Record/Subdivision.php b/src/GeoIP2/Record/Subdivision.php index 581b5a8..b209c0e 100644 --- a/src/GeoIP2/Record/Subdivision.php +++ b/src/GeoIP2/Record/Subdivision.php @@ -4,8 +4,10 @@ namespace GeoIP2\Record; class Subdivision extends AbstractPlaceRecord { - protected $validAttributes = Array('confidence', - 'geonameId', - 'isoCode', - 'names'); -} \ No newline at end of file + protected $validAttributes = array( + 'confidence', + 'geonameId', + 'isoCode', + 'names' + ); +} diff --git a/src/GeoIP2/Record/Traits.php b/src/GeoIP2/Record/Traits.php index 52816c3..095a3a8 100644 --- a/src/GeoIP2/Record/Traits.php +++ b/src/GeoIP2/Record/Traits.php @@ -4,14 +4,15 @@ namespace GeoIP2\Record; class Traits extends AbstractRecord { - protected $validAttributes = Array('autonomousSystemNumber', - 'autonomousSystemOrganization', - 'domain', - 'isAnonymousProxy', - 'isSatelliteProvider', - 'isp', - 'ipAddress', - 'organization', - 'userType'); - -} \ No newline at end of file + protected $validAttributes = array( + 'autonomousSystemNumber', + 'autonomousSystemOrganization', + 'domain', + 'isAnonymousProxy', + 'isSatelliteProvider', + 'isp', + 'ipAddress', + 'organization', + 'userType' + ); +} diff --git a/src/GeoIP2/Webservice/Client.php b/src/GeoIP2/Webservice/Client.php index 44b5b31..5625de6 100644 --- a/src/GeoIP2/Webservice/Client.php +++ b/src/GeoIP2/Webservice/Client.php @@ -17,134 +17,164 @@ use Guzzle\Http\Exception\ServerErrorResponseException; class Client { - private $userId; - private $licenseKey; - private $languages; - private $baseUri = 'https://geoip.maxmind.com/geoip/v2.0'; - private $guzzleClient; + private $userId; + private $licenseKey; + private $languages; + private $baseUri = 'https://geoip.maxmind.com/geoip/v2.0'; + private $guzzleClient; - public function __construct($userId, $licenseKey, $languages=array('en'), - $guzzleClient = null) - { - $this->userId = $userId; - $this->licenseKey = $licenseKey; - $this->languages = $languages; - // To enable unit testing - $this->guzzleClient = $guzzleClient; - } - - public function city($ipAddress = 'me') - { - return $this->responseFor('city', 'City', $ipAddress); - } - - public function country($ipAddress = 'me') - { - return $this->responseFor('country', 'Country', $ipAddress); - } - - public function cityIspOrg($ipAddress = 'me') - { - return $this->responseFor('city_isp_org', 'CityIspOrg', $ipAddress); - } - - public function omni($ipAddress = 'me') - { - return $this->responseFor('omni', 'Omni', $ipAddress); - } - - private function responseFor($path, $class, $ipAddress) - { - $uri = implode('/', array($this->baseUri, $path, $ipAddress)); - - $client = $this->guzzleClient ? $this->guzzleClient : new GuzzleClient(); - $request = $client->get($uri, array('Accept' => 'application/json')); - $request->setAuth($this->userId, $this->licenseKey); - $ua = $request->getHeader('User-Agent'); - $ua = "GeoIP2 PHP API ($ua)"; - $request->setHeader('User-Agent', $ua); - - $response = null; - try{ - $response = $request->send(); - } - catch (ClientErrorResponseException $e) { - $this->handle4xx($e->getResponse(), $uri); - } - catch (ServerErrorResponseException $e) { - $this->handle5xx($e->getResponse(), $uri); + public function __construct( + $userId, + $licenseKey, + $languages = array('en'), + $guzzleClient = null + ) { + $this->userId = $userId; + $this->licenseKey = $licenseKey; + $this->languages = $languages; + // To enable unit testing + $this->guzzleClient = $guzzleClient; } - if ($response && $response->isSuccessful()) { - $body = $this->handleSuccess($response, $uri); - $class = "GeoIP2\\Model\\" . $class; - return new $class($body, $this->languages); - } - else { - $this->handleNon200($response, $uri); - } - } - - private function handleSuccess($response, $uri) - { - if ($response->getContentLength() == 0) { - throw new GenericException("Received a 200 response for $uri but did not receive a HTTP body."); + public function city($ipAddress = 'me') + { + return $this->responseFor('city', 'City', $ipAddress); } - try { - return $response->json(); + public function country($ipAddress = 'me') + { + return $this->responseFor('country', 'Country', $ipAddress); } - catch (RuntimeException $e) { - throw new GenericException("Received a 200 response for $uri but could not decode the response as JSON: " . $e->getMessage()); + public function cityIspOrg($ipAddress = 'me') + { + return $this->responseFor('city_isp_org', 'CityIspOrg', $ipAddress); } - } - private function handle4xx($response, $uri) - { - $status = $response->getStatusCode(); + public function omni($ipAddress = 'me') + { + return $this->responseFor('omni', 'Omni', $ipAddress); + } - $body = array(); + private function responseFor($path, $class, $ipAddress) + { + $uri = implode('/', array($this->baseUri, $path, $ipAddress)); - if ( $response->getContentLength() > 0 ) { - if( strstr($response->getContentType(), 'json')) { + $client = $this->guzzleClient ? + $this->guzzleClient : new GuzzleClient(); + $request = $client->get($uri, array('Accept' => 'application/json')); + $request->setAuth($this->userId, $this->licenseKey); + $ua = $request->getHeader('User-Agent'); + $ua = "GeoIP2 PHP API ($ua)"; + $request->setHeader('User-Agent', $ua); + + $response = null; try { - $body = $response->json(); - if (!isset($body['code']) || !isset($body['error']) ){ - throw new GenericException('Response contains JSON but it does not specify code or error keys: ' . $response->getBody()); - } + $response = $request->send(); + } catch (ClientErrorResponseException $e) { + $this->handle4xx($e->getResponse(), $uri); + } catch (ServerErrorResponseException $e) { + $this->handle5xx($e->getResponse(), $uri); } - catch (RuntimeException $e){ - throw new HttpException("Received a $status error for $uri but it did not include the expected JSON body: " . $e->getMessage(), $status, $uri); + + if ($response && $response->isSuccessful()) { + $body = $this->handleSuccess($response, $uri); + $class = "GeoIP2\\Model\\" . $class; + return new $class($body, $this->languages); + } else { + $this->handleNon200($response, $uri); } - } - else { - throw new HttpException("Received a $status error for $uri with the following body: " . $response->getBody(), - $status, $uri); - } - } - else { - throw new HttpException("Received a $status error for $uri with no body", - $status, $uri); } - throw new WebserviceException($body['error'], $body['code'], $status, $uri); - } + private function handleSuccess($response, $uri) + { + if ($response->getContentLength() == 0) { + throw new GenericException( + "Received a 200 response for $uri but did not " . + "receive a HTTP body." + ); + } - private function handle5xx($response, $uri) - { - $status = $response->getStatusCode(); + try { + return $response->json(); + } catch (RuntimeException $e) { + throw new GenericException( + "Received a 200 response for $uri but could not decode " . + "the response as JSON: " . $e->getMessage() + ); - throw new HttpException("Received a server error ($status) for $uri", - $status,$uri); - } + } + } - private function handleNon200($response, $uri) - { - $status = $response->getStatusCode(); + private function handle4xx($response, $uri) + { + $status = $response->getStatusCode(); - throw new HttpException("Received a very surprising HTTP status " . - "($status) for $uri", - $status, $uri); - } + $body = array(); + + if ($response->getContentLength() > 0) { + if (strstr($response->getContentType(), 'json')) { + try { + $body = $response->json(); + if (!isset($body['code']) || !isset($body['error'])) { + throw new GenericException( + 'Response contains JSON but it does not specify ' . + 'code or error keys: ' . $response->getBody() + ); + } + } catch (RuntimeException $e) { + throw new HttpException( + "Received a $status error for $uri but it did not " . + "include the expected JSON body: " . + $e->getMessage(), + $status, + $uri + ); + } + } else { + throw new HttpException( + "Received a $status error for $uri with the " . + "following body: " . $response->getBody(), + $status, + $uri + ); + } + } else { + throw new HttpException( + "Received a $status error for $uri with no body", + $status, + $uri + ); + } + + throw new WebserviceException( + $body['error'], + $body['code'], + $status, + $uri + ); + } + + private function handle5xx($response, $uri) + { + $status = $response->getStatusCode(); + + throw new HttpException( + "Received a server error ($status) for $uri", + $status, + $uri + ); + } + + private function handleNon200($response, $uri) + { + $status = $response->getStatusCode(); + + throw new HttpException( + "Received a very surprising HTTP status " . + "($status) for $uri", + $status, + $uri + ); + } } diff --git a/tests/GeoIP2/Test/Model/CountryTest.php b/tests/GeoIP2/Test/Model/CountryTest.php index e535659..5c80e10 100644 --- a/tests/GeoIP2/Test/Model/CountryTest.php +++ b/tests/GeoIP2/Test/Model/CountryTest.php @@ -8,7 +8,7 @@ class CountryTest extends \PHPUnit_Framework_TestCase { private $raw = array( - 'continent' => array( + 'continent' => array( 'continent_code' => 'NA', 'geoname_id' => 42, 'names' => array( 'en' => 'North America' ), @@ -30,101 +30,133 @@ class CountryTest extends \PHPUnit_Framework_TestCase private $model; - public function setUp () { - $this->model = new Country($this->raw, ['en']); - + public function setUp () + { + $this->model = new Country($this->raw, ['en']); } - public function testObjects () { - $this->assertInstanceOf('GeoIP2\Model\Country', $this->model, - 'minimal GeoIP2::Model::Country object'); - $this->assertInstanceOf('GeoIP2\Record\Continent', $this->model->continent); - $this->assertInstanceOf('GeoIP2\Record\Country', $this->model->country); - $this->assertInstanceOf('GeoIP2\Record\Country', $this->model->registeredCountry); - $this->assertInstanceOf('GeoIP2\Record\RepresentedCountry', - $this->model->representedCountry); - $this->assertInstanceOf('GeoIP2\Record\Traits', $this->model->traits); - } - - public function testValues() { - - $this->assertEquals(42, $this->model->continent->geonameId, - 'continent geoname_id is 42'); - - $this->assertEquals('NA', $this->model->continent->continentCode, - 'continent continent_code is NA'); - - $this->assertEquals(array( 'en' => 'North America' ), - $this->model->continent->names, - 'continent names'); - - $this->assertEquals( - 'North America', - $this->model->continent->name, - 'continent name is North America'); - - $this->assertEquals( - 1, - $this->model->country->geonameId, - 'country geoname_id is 1' - ); - - $this->assertEquals( - 'US', - $this->model->country->isoCode, - 'country iso_code is US' - ); - - $this->assertEquals( - array( 'en' => 'United States of America' ), - $this->model->country->names, - 'country names' - ); - - $this->assertEquals( - $this->model->country->name, - 'United States of America', - 'country name is United States of America' - ); - - $this->assertEquals( - null, - $this->model->country->confidence, - 'country confidence is undef' - ); - - $this->assertEquals(2, $this->model->registeredCountry->geonameId, - 'registered_country geoname_id is 2' - ); - - $this->assertEquals('CA', - $this->model->registeredCountry->isoCode, - 'registered_country iso_code is CA' - ); - - $this->assertEquals( - array( 'en' => 'Canada' ), - $this->model->registeredCountry->names, - 'registered_country names' - ); - - $this->assertEquals( - 'Canada', - $this->model->registeredCountry->name, - 'registered_country name is Canada' - ); - - foreach (array( 'isAnonymousProxy', 'isSatelliteProvider' ) as $meth) { - - $this->assertEquals(0, $this->model->traits->$meth, - "traits $meth returns 0 by default" + public function testObjects () + { + $this->assertInstanceOf( + 'GeoIP2\Model\Country', + $this->model, + 'minimal GeoIP2::Model::Country object' + ); + $this->assertInstanceOf( + 'GeoIP2\Record\Continent', + $this->model->continent + ); + $this->assertInstanceOf( + 'GeoIP2\Record\Country', + $this->model->country + ); + $this->assertInstanceOf( + 'GeoIP2\Record\Country', + $this->model->registeredCountry + ); + $this->assertInstanceOf( + 'GeoIP2\Record\RepresentedCountry', + $this->model->representedCountry + ); + $this->assertInstanceOf( + 'GeoIP2\Record\Traits', + $this->model->traits ); } - $this->assertEquals( - $this->raw, - $this->model->raw, - 'raw method returns raw input' - ); + public function testValues() + { + + $this->assertEquals( + 42, + $this->model->continent->geonameId, + 'continent geoname_id is 42' + ); + + $this->assertEquals( + 'NA', + $this->model->continent->continentCode, + 'continent continent_code is NA' + ); + + $this->assertEquals( + array( 'en' => 'North America' ), + $this->model->continent->names, + 'continent names' + ); + + $this->assertEquals( + 'North America', + $this->model->continent->name, + 'continent name is North America' + ); + + $this->assertEquals( + 1, + $this->model->country->geonameId, + 'country geoname_id is 1' + ); + + $this->assertEquals( + 'US', + $this->model->country->isoCode, + 'country iso_code is US' + ); + + $this->assertEquals( + array( 'en' => 'United States of America' ), + $this->model->country->names, + 'country name' + ); + + $this->assertEquals( + $this->model->country->name, + 'United States of America', + 'country name is United States of America' + ); + + $this->assertEquals( + null, + $this->model->country->confidence, + 'country confidence is undef' + ); + + $this->assertEquals( + 2, + $this->model->registeredCountry->geonameId, + 'registered_country geoname_id is 2' + ); + + $this->assertEquals( + 'CA', + $this->model->registeredCountry->isoCode, + 'registered_country iso_code is CA' + ); + + $this->assertEquals( + array( 'en' => 'Canada' ), + $this->model->registeredCountry->names, + 'registered_country names' + ); + + $this->assertEquals( + 'Canada', + $this->model->registeredCountry->name, + 'registered_country name is Canada' + ); + + foreach (array( 'isAnonymousProxy', 'isSatelliteProvider' ) as $meth) { + $this->assertEquals( + 0, + $this->model->traits->$meth, + "traits $meth returns 0 by default" + ); + } + + $this->assertEquals( + $this->raw, + $this->model->raw, + 'raw method returns raw input' + ); } } diff --git a/tests/GeoIP2/Test/Webservice/ClientTest.php b/tests/GeoIP2/Test/Webservice/ClientTest.php index 74510a0..a8ecf29 100644 --- a/tests/GeoIP2/Test/Webservice/ClientTest.php +++ b/tests/GeoIP2/Test/Webservice/ClientTest.php @@ -10,298 +10,345 @@ use Guzzle\Plugin\Mock\MockPlugin; class ClientTest extends \PHPUnit_Framework_TestCase { - private $country - = array( + private $country + = array( 'continent' => array( - 'continent_code' => 'NA', - 'geoname_id' => 42, - 'names' => array( 'en' => 'North America' ), - ), + 'continent_code' => 'NA', + 'geoname_id' => 42, + 'names' => array( 'en' => 'North America' ), + ), 'country' => array( - 'geoname_id' => 1, - 'iso_code' => 'US', - 'names' => array( 'en' => 'United States of America' ), - ), + 'geoname_id' => 1, + 'iso_code' => 'US', + 'names' => array( 'en' => 'United States of America' ), + ), 'traits' => array( - 'ip_address' => '1.2.3.4', - ), - ); + 'ip_address' => '1.2.3.4', + ), + ); - private function getResponse($ip) { - $responses = array( - '1.2.3.4' => $this->response( - 'country', - 200, - $this->country - ), - 'me' => $this->response( - 'country', - 200, - $this->country - ), - '1.2.3.5' => $this->response('country', 200), - '2.2.3.5' => $this->response('country', 200, 'bad body'), - '1.2.3.6'=> $this->response( - 'error', 400, - array( - 'code' => 'IP_ADDRESS_INVALID', - 'error' => 'The value "1.2.3" is not a valid ip address' - ) - ), - '1.2.3.7' => $this->response( - 'error', - 400 - ), - '1.2.3.8' => $this->response( - 'error', - 400, - array( 'weird' => 42 ) - ), - '1.2.3.9' => $this->response( - 'error', - 400, - null, - 'bad body' - ), - '1.2.3.10' => $this->response( - null, - 500 - ), - '1.2.3.11' => $this->response( - null, - 300 - ), - '1.2.3.12' => $this->response( - 'error', - 406, - 'Cannot satisfy your Accept-Charset requirements', - null, - 'text/plain' - ), - ); - return $responses[$ip]; - } - - public function testCountry() { - $country = $this->client($this->getResponse('1.2.3.4'))->country('1.2.3.4' ); - - $this->assertInstanceOf('GeoIP2\Model\Country', $country); - - $this->assertEquals(42, $country->continent->geonameId, - 'continent geoname_id is 42'); - - $this->assertEquals('NA', $country->continent->continentCode, - 'continent continent_code is NA'); - - $this->assertEquals(array('en' => 'North America'), - $country->continent->names, 'continent names'); - - $this->assertEquals('North America', $country->continent->name, - 'continent name is North America'); - - $this->assertEquals(1, $country->country->geonameId, - 'country geoname_id is 1'); - - $this->assertEquals('US', $country->country->isoCode, - 'country iso_code is US'); - - $this->assertEquals(array( 'en' => 'United States of America' ), - $country->country->names, 'country names'); - - $this->assertEquals('United States of America', - $country->country->name, - 'country name is United States of America'); - } - - public function testMe() - { - $client = $this->client($this->getResponse('me')); - - $this->assertInstanceOf('GeoIP2\Model\CityIspOrg', - $client->cityIspOrg('me' ), - 'can set ip parameter to me'); - } - - /** - * @expectedException GeoIP2\Exception\GenericException - * @expectedExceptionMessage Received a 200 response for https://geoip.maxmind.com/geoip/v2.0/country/1.2.3.5 but did not receive a HTTP body. - */ - public function testNoBodyException() - { - $client = $this->client($this->getResponse('1.2.3.5')); - - $client->country('1.2.3.5'); - } - - /** - * @expectedException GeoIP2\Exception\GenericException - * @expectedExceptionMessage Received a 200 response for https://geoip.maxmind.com/geoip/v2.0/country/2.2.3.5 but could not decode the response as JSON: - */ - public function testBadBodyException() - { - $client = $this->client($this->getResponse('2.2.3.5')); - - $client->country('2.2.3.5'); - } - - - /** - * @expectedException GeoIP2\Exception\WebserviceException - * @expectedExceptionCode IP_ADDRESS_INVALID - * @expectedExceptionMessage The value "1.2.3" is not a valid ip address - */ - public function testInvalidIPException() - { - $client = $this->client($this->getResponse('1.2.3.6')); - - $client->country('1.2.3.6'); - - } - - /** - * @expectedException GeoIP2\Exception\HttpException - * @expectedExceptionCode 400 - * @expectedExceptionMessage with no body - */ - public function testNoErrorBodyIPException() - { - $client = $this->client($this->getResponse('1.2.3.7')); - - $client->country('1.2.3.7'); - - } - - /** - * @expectedException GeoIP2\Exception\GenericException - * @expectedExceptionMessage Response contains JSON but it does not specify code or error keys - */ - public function testWeirdErrorBodyIPException() - { - $client = $this->client($this->getResponse('1.2.3.8')); - - $client->country('1.2.3.8'); - - } - - /** - * @expectedException GeoIP2\Exception\HttpException - * @expectedExceptionCode 400 - * @expectedExceptionMessage did not include the expected JSON body - */ - public function testInvalidErrorBodyIPException() - { - $client = $this->client($this->getResponse('1.2.3.9')); - - $client->country('1.2.3.9'); - - } - - /** - * @expectedException GeoIP2\Exception\HttpException - * @expectedExceptionCode 500 - * @expectedExceptionMessage Received a server error (500) - */ - public function test500PException() - { - $client = $this->client($this->getResponse('1.2.3.10')); - - $client->country('1.2.3.10'); - - } - - /** - * @expectedException GeoIP2\Exception\HttpException - * @expectedExceptionCode 300 - * @expectedExceptionMessage Received a very surprising HTTP status (300) - */ - public function test3xxException() - { - $client = $this->client($this->getResponse('1.2.3.11')); - - $client->country('1.2.3.11'); - - } - - /** - * @expectedException GeoIP2\Exception\HttpException - * @expectedExceptionCode 406 - * @expectedExceptionMessage Received a 406 error for https://geoip.maxmind.com/geoip/v2.0/country/1.2.3.12 with the following body: Cannot satisfy your Accept-Charset requirements - */ - public function test406Exception() - { - $client = $this->client($this->getResponse('1.2.3.12')); - - $client->country('1.2.3.12'); - - } - - public function testParams() { - $plugin = new MockPlugin(); - $plugin->addResponse($this->getResponse('1.2.3.4')); - $guzzleClient = new GuzzleClient(); - $guzzleClient->addSubscriber($plugin); - - $client = new Client(42, 'abcdef123456', array('en'), - $guzzleClient); - $client->country('1.2.3.4'); - - $request = $plugin->getReceivedRequests()[0]; - - $this->assertEquals('https://geoip.maxmind.com/geoip/v2.0/country/1.2.3.4', - $request->getUrl(), - 'got expected URI for Country request'); - $this->assertEquals('GET', $request->getMethod(), 'request is a GET'); - - $this->assertEquals('application/json', $request->getHeader('Accept'), - 'request sets Accept header to application/json'); - - $this->assertStringMatchesFormat('GeoIP2 PHP API (Guzzle%s)', - $request->getHeader('User-Agent') . '', - 'request sets Accept header to application/json'); - - - } - - - private function client($response, $languages=array('en')) { - $plugin = new MockPlugin(); - $plugin->addResponse($response); - $guzzleClient = new GuzzleClient(); - $guzzleClient->addSubscriber($plugin); - - $client = new Client(42, 'abcdef123456', $languages, - $guzzleClient); - - return $client; - } - - private function response($endpoint, $status, $body=null, - $bad=null, $contentType=null) - { - $headers = Array(); - if( $contentType) { - $headers['Content-Type'] = $contentType; - } - elseif ( $status == 200 || ( $status >= 400 && $status < 500 ) ) { - $headers['Content-Type'] = 'application/vnd.maxmind.com-' - . $endpoint . '+json; charset=UTF-8; version=1.0;'; + private function getResponse($ip) + { + $responses = array( + '1.2.3.4' => $this->response( + 'country', + 200, + $this->country + ), + 'me' => $this->response( + 'country', + 200, + $this->country + ), + '1.2.3.5' => $this->response('country', 200), + '2.2.3.5' => $this->response('country', 200, 'bad body'), + '1.2.3.6'=> $this->response( + 'error', + 400, + array( + 'code' => 'IP_ADDRESS_INVALID', + 'error' => 'The value "1.2.3" is not a valid ip address' + ) + ), + '1.2.3.7' => $this->response( + 'error', + 400 + ), + '1.2.3.8' => $this->response( + 'error', + 400, + array( 'weird' => 42 ) + ), + '1.2.3.9' => $this->response( + 'error', + 400, + null, + 'bad body' + ), + '1.2.3.10' => $this->response( + null, + 500 + ), + '1.2.3.11' => $this->response( + null, + 300 + ), + '1.2.3.12' => $this->response( + 'error', + 406, + 'Cannot satisfy your Accept-Charset requirements', + null, + 'text/plain' + ), + ); + return $responses[$ip]; } - if ($bad) { - $body = '{ invalid: }'; - } - elseif (is_array($body)) { - $body = json_encode($body); + public function testCountry() + { + $country = $this->client($this->getResponse('1.2.3.4')) + ->country('1.2.3.4'); + + $this->assertInstanceOf('GeoIP2\Model\Country', $country); + + $this->assertEquals( + 42, + $country->continent->geonameId, + 'continent geoname_id is 42' + ); + + $this->assertEquals( + 'NA', + $country->continent->continentCode, + 'continent continent_code is NA' + ); + + $this->assertEquals( + array('en' => 'North America'), + $country->continent->names, + 'continent names' + ); + + $this->assertEquals( + 'North America', + $country->continent->name, + 'continent name is North America' + ); + + $this->assertEquals( + 1, + $country->country->geonameId, + 'country geoname_id is 1' + ); + + $this->assertEquals( + 'US', + $country->country->isoCode, + 'country iso_code is US' + ); + + $this->assertEquals( + array( 'en' => 'United States of America' ), + $country->country->names, + 'country names' + ); + + $this->assertEquals( + 'United States of America', + $country->country->name, + 'country name is United States of America' + ); } - $headers['Content-Length'] = strlen($body); + public function testMe() + { + $client = $this->client($this->getResponse('me')); - return new Response($status, $headers, $body); - } + $this->assertInstanceOf( + 'GeoIP2\Model\CityIspOrg', + $client->cityIspOrg('me'), + 'can set ip parameter to me' + ); + } - public function testTest() - { - $this->assertEquals(1,1); - } -} \ No newline at end of file + /** + * @expectedException GeoIP2\Exception\GenericException + * @expectedExceptionMessage Received a 200 response for https://geoip.maxmind.com/geoip/v2.0/country/1.2.3.5 but did not receive a HTTP body. + */ + public function testNoBodyException() + { + $client = $this->client($this->getResponse('1.2.3.5')); + + $client->country('1.2.3.5'); + } + + /** + * @expectedException GeoIP2\Exception\GenericException + * @expectedExceptionMessage Received a 200 response for https://geoip.maxmind.com/geoip/v2.0/country/2.2.3.5 but could not decode the response as JSON: + */ + public function testBadBodyException() + { + $client = $this->client($this->getResponse('2.2.3.5')); + + $client->country('2.2.3.5'); + } + + + /** + * @expectedException GeoIP2\Exception\WebserviceException + * @expectedExceptionCode IP_ADDRESS_INVALID + * @expectedExceptionMessage The value "1.2.3" is not a valid ip address + */ + public function testInvalidIPException() + { + $client = $this->client($this->getResponse('1.2.3.6')); + + $client->country('1.2.3.6'); + + } + + /** + * @expectedException GeoIP2\Exception\HttpException + * @expectedExceptionCode 400 + * @expectedExceptionMessage with no body + */ + public function testNoErrorBodyIPException() + { + $client = $this->client($this->getResponse('1.2.3.7')); + + $client->country('1.2.3.7'); + } + + /** + * @expectedException GeoIP2\Exception\GenericException + * @expectedExceptionMessage Response contains JSON but it does not specify code or error keys + */ + public function testWeirdErrorBodyIPException() + { + $client = $this->client($this->getResponse('1.2.3.8')); + + $client->country('1.2.3.8'); + + } + + /** + * @expectedException GeoIP2\Exception\HttpException + * @expectedExceptionCode 400 + * @expectedExceptionMessage did not include the expected JSON body + */ + public function testInvalidErrorBodyIPException() + { + $client = $this->client($this->getResponse('1.2.3.9')); + + $client->country('1.2.3.9'); + + } + + /** + * @expectedException GeoIP2\Exception\HttpException + * @expectedExceptionCode 500 + * @expectedExceptionMessage Received a server error (500) + */ + public function test500PException() + { + $client = $this->client($this->getResponse('1.2.3.10')); + + $client->country('1.2.3.10'); + + } + + /** + * @expectedException GeoIP2\Exception\HttpException + * @expectedExceptionCode 300 + * @expectedExceptionMessage Received a very surprising HTTP status (300) + */ + public function test3xxException() + { + $client = $this->client($this->getResponse('1.2.3.11')); + + $client->country('1.2.3.11'); + + } + + /** + * @expectedException GeoIP2\Exception\HttpException + * @expectedExceptionCode 406 + * @expectedExceptionMessage Received a 406 error for https://geoip.maxmind.com/geoip/v2.0/country/1.2.3.12 with the following body: Cannot satisfy your Accept-Charset requirements + */ + public function test406Exception() + { + $client = $this->client($this->getResponse('1.2.3.12')); + $client->country('1.2.3.12'); + } + + public function testParams() + { + $plugin = new MockPlugin(); + $plugin->addResponse($this->getResponse('1.2.3.4')); + $guzzleClient = new GuzzleClient(); + $guzzleClient->addSubscriber($plugin); + + $client = new Client( + 42, + 'abcdef123456', + array('en'), + $guzzleClient + ); + $client->country('1.2.3.4'); + + $request = $plugin->getReceivedRequests()[0]; + + $this->assertEquals( + 'https://geoip.maxmind.com/geoip/v2.0/country/1.2.3.4', + $request->getUrl(), + 'got expected URI for Country request' + ); + $this->assertEquals( + 'GET', + $request->getMethod(), + 'request is a GET' + ); + + $this->assertEquals( + 'application/json', + $request->getHeader('Accept'), + 'request sets Accept header to application/json' + ); + + $this->assertStringMatchesFormat( + 'GeoIP2 PHP API (Guzzle%s)', + $request->getHeader('User-Agent') . '', + 'request sets Accept header to application/json' + ); + } + + + private function client($response, $languages = array('en')) + { + $plugin = new MockPlugin(); + $plugin->addResponse($response); + $guzzleClient = new GuzzleClient(); + $guzzleClient->addSubscriber($plugin); + + $client = new Client( + 42, + 'abcdef123456', + $languages, + $guzzleClient + ); + + return $client; + } + + private function response( + $endpoint, + $status, + $body = null, + $bad = null, + $contentType = null + ) { + $headers = array(); + if ($contentType) { + $headers['Content-Type'] = $contentType; + } elseif ($status == 200 || ( $status >= 400 && $status < 500 )) { + $headers['Content-Type'] = 'application/vnd.maxmind.com-' + . $endpoint . '+json; charset=UTF-8; version=1.0;'; + } + + if ($bad) { + $body = '{ invalid: }'; + } elseif (is_array($body)) { + $body = json_encode($body); + } + + $headers['Content-Length'] = strlen($body); + + return new Response($status, $headers, $body); + } + + public function testTest() + { + $this->assertEquals(1, 1); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 20e17ed..55b6856 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -5,4 +5,3 @@ if (!$loader = @include __DIR__.'/../vendor/autoload.php') { } $loader->add('GeoIP2\Test', __DIR__); -