25 Commits

Author SHA1 Message Date
Gregory Oschwald
01f58d749b Prepare for 2.1.1 2014-12-03 06:59:16 -08:00
Gregory Oschwald
64f2262093 Fix a couple minor release script issues 2014-10-29 10:11:44 -07:00
Dave Rolsky
8ef95cb4d1 Merge pull request #32 from maxmind/greg/release-updates
Automatically download apigen/box and run box
2014-10-29 11:35:19 -05:00
Gregory Oschwald
076213aedb Switch another <code> usage 2014-10-29 09:03:25 -07:00
Gregory Oschwald
1546532b39 Prepare for 2.1.0 2014-10-29 08:48:07 -07:00
Gregory Oschwald
f1fe6587b4 Fix outdated docs and use ` instead of <code> 2014-10-29 08:46:57 -07:00
Gregory Oschwald
2d6d43b62c Bump next release to 2.1.0 as it adds new features 2014-10-28 15:44:49 -07:00
Gregory Oschwald
09cf864045 Be sure to include all LICENSE files in phar 2014-10-28 14:52:18 -07:00
Gregory Oschwald
4ae7983706 Automatically download apigen/box and run box 2014-10-28 14:18:33 -07:00
Gregory Oschwald
3142e44b3e Merge pull request #31 from maxmind/dave/boolean-false-not-null
Return false instead of null for non-true boolean attributes
2014-10-28 10:49:29 -07:00
Gregory Oschwald
4bdb050a50 Fix misname property in model docs 2014-10-28 10:11:42 -07:00
Dave Rolsky
c44053c276 Return false instead of null for boolean attributes 2014-10-28 11:28:02 -05:00
Gregory Oschwald
caf91dd247 Merge pull request #30 from maxmind/dave/anonymous-ip-database
Add support for the GeoIP2 Anonymous IP database
2014-10-28 09:18:47 -07:00
Dave Rolsky
ffc6493c8d Fix small typo in CHANGELOG.md 2014-10-28 10:31:30 -05:00
Dave Rolsky
e5f61fd275 Add example for Anonymous-IP database in README.md 2014-10-28 10:10:37 -05:00
Dave Rolsky
6859340968 Add Changes for Anonymous IP support 2014-10-27 17:24:27 -05:00
Dave Rolsky
970d1dba45 Fix return vlaue docs for anonymousIp method 2014-10-27 17:21:38 -05:00
Dave Rolsky
9e6449290f Use assertSame instead of assertEquals to test boolean attributes 2014-10-27 17:21:10 -05:00
Dave Rolsky
0c6ba34623 Remove apigen dep 2014-10-27 16:39:20 -05:00
Dave Rolsky
fbf4583b3e Add support for Anonymous IP database 2014-10-27 16:30:40 -05:00
Dave Rolsky
18686e11ac Add docs for all model-returning methods on the Reader class 2014-10-27 16:06:26 -05:00
Gregory Oschwald
00a520f3c5 Remove incorrect doc 2014-09-29 13:16:23 -07:00
Gregory Oschwald
6cd0863499 Pin apigen at exactly 2.8.2. Everything else is broken 2014-09-22 16:33:18 -07:00
Gregory Oschwald
5407b4f7c6 Remove nette/nette pin so new version of apigen can be installed 2014-09-22 16:21:37 -07:00
Gregory Oschwald
c58034524e Prepare for 2.0.0 2014-09-22 10:49:45 -07:00
16 changed files with 331 additions and 90 deletions

4
.gitignore vendored
View File

@@ -2,13 +2,13 @@ _site
.gh-pages
.idea
GeoLite2-City.mmdb
apigen.phar
box.phar
build
composer.lock
composer.phar
phpunit.xml
geoip2.phar
geoip2-php.sublime-*
vendor/
*.sw?
t.php
*.old

View File

@@ -1,6 +1,28 @@
CHANGELOG
=========
2.1.1 (2014-12-03)
------------------
* The 2.1.0 Phar builds included a shebang line, causing issues when loading
it as a library. This has been corrected. GitHub #33.
2.1.0 (2014-10-29)
------------------
* Update ApiGen dependency to version that isn't broken on case sensitive
file systems.
* Added support for the GeoIP2 Anonymous IP database. The
`GeoIP2\Database\Reader` class now has an `anonymousIp` method which returns
a `GeoIP2\Model\AnonymousIp` object.
* Boolean attributes like those in the `GeoIP2\Record\Traits` class now return
`false` instead of `null` when they were not true.
2.0.0 (2014-09-22)
------------------
* First production release.
0.9.0 (2014-09-15)
------------------

View File

@@ -26,7 +26,7 @@ You should now have the file `composer.phar` in your project directory.
Run in your project root:
```
php composer.phar require geoip2/geoip2:~0.9.0
php composer.phar require geoip2/geoip2:~2.0
```
You should now have the files `composer.json` and `composer.lock` as well as
@@ -114,6 +114,24 @@ print($record->location->longitude . "\n"); // -93.2323
```
### Anonymous IP Example ###
```php
<?php
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;
// This creates the Reader object, which should be reused across
// lookups.
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Anonymous-IP.mmdb');
$record = $reader->anonymousIp('128.101.101.101');
if ($record->isAnonymous) { print "anon\n"; }
print($record->ipAddress . "\n"); // '128.101.101.101'
```
### Connection-Type Example ###
```php
@@ -238,9 +256,6 @@ for details on what data each end point may return.
The only piece of data which is always returned is the `ipAddress`
attribute in the `GeoIp2\Record\Traits` record.
Every record class attribute has a corresponding predicate method so you can
check to see if the attribute is set.
## Integration with GeoNames ##
[GeoNames](http://www.geonames.org/) offers web services and downloadable

View File

@@ -1,63 +0,0 @@
#!/bin/bash
TAG=$1
if [ -z $TAG ]; then
echo "Please specify a tag"
exit 1
fi
if [ -n "$(git status --porcelain)" ]; then
echo ". is not clean." >&2
exit 1
fi
if [ ! -d .gh-pages ]; then
echo "Checking out gh-pages in .gh-pages"
git clone -b gh-pages git@git.maxmind.com:GeoIP2-php .gh-pages
cd .gh-pages
else
echo "Updating .gh-pages"
cd .gh-pages
git pull
fi
if [ -n "$(git status --porcelain)" ]; then
echo ".gh-pages is not clean" >&2
exit 1
fi
../vendor/bin/apigen --quiet --download --title "GeoIP2 PHP API $TAG" --source ../src --destination doc/$TAG
PAGE=index.md
cat <<EOF > $PAGE
---
layout: default
title: MaxMind GeoIP2 PHP API
language: php
version: $TAG
---
EOF
cat ../README.md >> $PAGE
git add doc/
git commit -m "Updated for $TAG" -a
read -e -p "Push to origin? " SHOULD_PUSH
if [ "$SHOULD_PUSH" != "y" ]; then
echo "Aborting"
exit 1
fi
# If we don't push directly to github, the page doesn't get built for some
# reason.
git push git@github.com:maxmind/GeoIP2-php.git
git push
cd ..
git tag -a $TAG
git push
git push --tags

View File

@@ -13,6 +13,8 @@
"finder": [
{
"name": [
"LICENSE",
"LICENSE.*",
"*.php",
"*.pem",
"*.pem.md5"
@@ -27,8 +29,8 @@
"in": "vendor"
}
],
"directories": ["compat", "src/"],
"git-version": "git-version",
"shebang": "",
"stub": true
}

View File

@@ -14,13 +14,11 @@
],
"require": {
"guzzle/guzzle": "3.*",
"maxmind-db/reader": "~0.3.2",
"maxmind-db/reader": "~1.0",
"php": ">=5.3.1"
},
"require-dev": {
"apigen/apigen": "~2.8.0",
"nette/nette": "~2.1.3",
"phpunit/phpunit": "4.1.*",
"phpunit/phpunit": "4.2.*",
"satooshi/php-coveralls": "dev-master"
},
"autoload": {

16
dev-bin/phar-test.php Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env php
<?php
require_once 'geoip2.phar';
use GeoIp2\Database\Reader;
$reader = new Reader('maxmind-db/test-data/GeoIP2-City-Test.mmdb');
$record = $reader->city('81.2.69.160');
if ( $record->country->isoCode === 'GB' ) {
exit(0);
}
print('Problem with Phar!');
exit(1);

111
dev-bin/release.sh Executable file
View File

@@ -0,0 +1,111 @@
#!/bin/bash
set -e
TAG=$1
if [ -z $TAG ]; then
echo "Please specify a tag"
exit 1
fi
if [ -f geoip2.phar ]; then
rm geoip2.phar
fi
if [ -n "$(git status --porcelain)" ]; then
echo ". is not clean." >&2
exit 1
fi
if [ -d vendor ]; then
rm -fr vendor
fi
php composer.phar self-update
php composer.phar update --no-dev
# We currently use a custom version of Box due to
# https://github.com/box-project/box2/issues/88. There are PRs from Greg with
# the fixes.
#
# if [ ! -f box.phar ]; then
# wget -O box.phar "https://github.com/kherge-archive/Box/releases/download/2.4.4/box-2.4.4.phar"
# fi
../box2/bin/box build
./dev-bin/phar-test.php
# Download test deps
php composer.phar update
./vendor/bin/phpunit
if [ ! -d .gh-pages ]; then
echo "Checking out gh-pages in .gh-pages"
git clone -b gh-pages git@git.maxmind.com:GeoIP2-php .gh-pages
pushd .gh-pages
else
echo "Updating .gh-pages"
pushd .gh-pages
git pull
fi
if [ -n "$(git status --porcelain)" ]; then
echo ".gh-pages is not clean" >&2
exit 1
fi
# We no longer have apigen as a dependency in Composer as releases are
# sporadically deleted upstream and compatibility is often broken on patch
# releases.
if [ ! -f apigen.phar ]; then
wget -O apigen.phar "https://github.com/apigen/apigen/releases/download/v4.0.0-RC3/apigen-4.0.0-RC3.phar"
fi
cat <<EOF > apigen.neon
destination: doc/$TAG
source:
- ../src
title: "GeoIP2 PHP API $TAG"
EOF
php apigen.phar generate
PAGE=index.md
cat <<EOF > $PAGE
---
layout: default
title: MaxMind GeoIP2 PHP API
language: php
version: $TAG
---
EOF
cat ../README.md >> $PAGE
git add doc/
git commit -m "Updated for $TAG" -a
read -e -p "Push to origin? " SHOULD_PUSH
if [ "$SHOULD_PUSH" != "y" ]; then
echo "Aborting"
exit 1
fi
# If we don't push directly to github, the page doesn't get built for some
# reason.
git push git@github.com:maxmind/GeoIP2-php.git
git push
popd
git tag -a $TAG
git push
git push --tags

View File

@@ -8,13 +8,9 @@ use MaxMind\Db\Reader as DbReader;
/**
* Instances of this class provide a reader for the GeoIP2 database format.
* IP addresses can be looked up using the <code>country</code>
* and <code>city</code> methods. We also provide <code>cityIspOrg</code>
* and <code>omni</code> methods to ease compatibility with the web service
* client, although we may offer the ability to specify additional databases
* to replicate these web services in the future (e.g., the ISP/Org database).
* IP addresses can be looked up using the database specific methods.
*
* **Usage**
* ## Usage ##
*
* The basic API for this class is the same for every database. First, you
* create a reader object, specifying a file name. You then call the method
@@ -25,7 +21,7 @@ use MaxMind\Db\Reader as DbReader;
* the method you called. This model in turn contains multiple record classes,
* each of which represents part of the data returned by the database. If
* the database does not contain the requested information, the attributes
* on the record class will have a <code>null</code> value.
* on the record class will have a `null` value.
*
* If the address is not in the database, an
* {@link \GeoIp2\Exception\AddressNotFoundException} exception will be
@@ -91,6 +87,39 @@ class Reader implements ProviderInterface
return $this->modelFor('Country', 'Country', $ipAddress);
}
/**
* This method returns a GeoIP2 Anonymous IP model.
*
* @param string $ipAddress IPv4 or IPv6 address as a string.
*
* @return \GeoIp2\Model\AnonymousIp
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database.
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
*/
public function anonymousIp($ipAddress)
{
return $this->flatModelFor(
'AnonymousIp',
'GeoIP2-Anonymous-IP',
$ipAddress
);
}
/**
* This method returns a GeoIP2 Connection Type model.
*
* @param string $ipAddress IPv4 or IPv6 address as a string.
*
* @return \GeoIp2\Model\ConnectionType
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database.
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
*/
public function connectionType($ipAddress)
{
return $this->flatModelFor(
@@ -100,6 +129,18 @@ class Reader implements ProviderInterface
);
}
/**
* This method returns a GeoIP2 Domain model.
*
* @param string $ipAddress IPv4 or IPv6 address as a string.
*
* @return \GeoIp2\Model\Domain
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database.
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
*/
public function domain($ipAddress)
{
return $this->flatModelFor(
@@ -109,6 +150,18 @@ class Reader implements ProviderInterface
);
}
/**
* This method returns a GeoIP2 ISP model.
*
* @param string $ipAddress IPv4 or IPv6 address as a string.
*
* @return \GeoIp2\Model\Isp
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database.
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
*/
public function isp($ipAddress)
{
return $this->flatModelFor(

View File

@@ -23,7 +23,15 @@ abstract class AbstractModel implements \JsonSerializable
*/
protected function get($field)
{
return isset($this->raw[$field]) ? $this->raw[$field] : null;
if (isset($this->raw[$field])) {
return $this->raw[$field];
} else {
if (preg_match('/^is_/', $field)) {
return false;
} else {
return null;
}
}
}
/**

View File

@@ -0,0 +1,50 @@
<?php
namespace GeoIp2\Model;
/**
* This class provides the GeoIP2 Anonymous IP model.
*
* @property boolean $isAnonymous This is true if the IP address belongs to
* any sort of anonymous network.
*
* @property boolean $isAnonymousVpn This is true if the IP address belongs to
* an anonymous VPN system.
*
* @property boolean $isHostingProvider This is true if the IP address belongs
* to a hosting provider.
*
* @property boolean $isPublicProxy This is true if the IP address belongs to
* a public proxy.
*
* @property boolean $isTorExitNode This is true if the IP address is a Tor
* exit node.
*
* @property string $ipAddress The IP address that the data in the model is
* for.
*
*/
class AnonymousIp extends AbstractModel
{
protected $isAnonymous;
protected $isAnonymousVpn;
protected $isHostingProvider;
protected $isPublicProxy;
protected $isTorExitNode;
protected $ipAddress;
/**
* @ignore
*/
public function __construct($raw)
{
parent::__construct($raw);
$this->isAnonymous = $this->get('is_anonymous');
$this->isAnonymousVpn = $this->get('is_anonymous_vpn');
$this->isHostingProvider = $this->get('is_hosting_provider');
$this->isPublicProxy = $this->get('is_public_proxy');
$this->isTorExitNode = $this->get('is_tor_exit_node');
$this->ipAddress = $this->get('ip_address');
}
}

View File

@@ -25,7 +25,11 @@ abstract class AbstractRecord implements \JsonSerializable
if ($this->__isset($attr)) {
return $this->record[$key];
} elseif ($this->validAttribute($attr)) {
return null;
if (preg_match('/^is_/', $key)) {
return false;
} else {
return null;
}
} else {
throw new \RuntimeException("Unknown attribute: $attr");
}

View File

@@ -30,13 +30,12 @@ use Guzzle\Http\Exception\ServerErrorResponseException;
* The web service may not return any information for an entire record, in
* which case all of the attributes for that record class will be empty.
*
* **Usage**
* ## Usage ##
*
* The basic API for this class is the same for all of the web service end
* points. First you create a web service object with your MaxMind
* <code>$userId</code> and <code>$licenseKey</code>, then you call the method
* corresponding to a specific end point, passing it the IP address you want
* to look up.
* points. First you create a web service object with your MaxMind `$userId`
* and `$licenseKey`, then you call the method corresponding to a specific end
* point, passing it the IP address you want to look up.
*
* If the request succeeds, the method call will return a model class for
* the end point you called. This model in turn contains multiple record

View File

@@ -88,6 +88,20 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
$reader->close();
}
public function testAnonymousIp()
{
$reader = new Reader('maxmind-db/test-data/GeoIP2-Anonymous-IP-Test.mmdb');
$ipAddress = '1.2.0.1';
$record = $reader->anonymousIp($ipAddress);
$this->assertSame(true, $record->isAnonymous);
$this->assertSame(true, $record->isAnonymousVpn);
$this->assertSame(false, $record->isHostingProvider);
$this->assertSame(false, $record->isPublicProxy);
$this->assertSame(false, $record->isTorExitNode);
$this->assertEquals($ipAddress, $record->ipAddress);
$reader->close();
}
public function testConnectionType()
{

View File

@@ -62,7 +62,7 @@ class InsightsTest extends \PHPUnit_Framework_TestCase
'autonomous_system_organization' => 'AS Organization',
'domain' => 'example.com',
'ip_address' => '1.2.3.4',
'is_satellite_provider' => 1,
'is_satellite_provider' => true,
'isp' => 'Comcast',
'organization' => 'Blorg',
'user_type' => 'college',
@@ -130,6 +130,18 @@ class InsightsTest extends \PHPUnit_Framework_TestCase
'$model->traits'
);
$this->assertSame(
true,
$model->traits->isSatelliteProvider,
'$model->traits->isSatelliteProvider is true'
);
$this->assertSame(
false,
$model->traits->isAnonymousProxy,
'$model->traits->isAnonymousProxy is false'
);
$this->assertEquals(
22,
$model->maxmind->queriesRemaining,