1: <?php
2:
3: namespace GeoIp2\Database;
4:
5: use GeoIp2\Exception\AddressNotFoundException;
6: use GeoIp2\ProviderInterface;
7: use MaxMind\Db\Reader as DbReader;
8:
9: /**
10: * Instances of this class provide a reader for the GeoIP2 database format.
11: * IP addresses can be looked up using the <code>country</code>
12: * and <code>city</code> methods. We also provide <code>cityIspOrg</code>
13: * and <code>omni</code> methods to ease compatibility with the web service
14: * client, although we may offer the ability to specify additional databases
15: * to replicate these web services in the future (e.g., the ISP/Org database).
16: *
17: * **Usage**
18: *
19: * The basic API for this class is the same for every database. First, you
20: * create a reader object, specifying a file name. You then call the method
21: * corresponding to the specific database, passing it the IP address you want
22: * to look up.
23: *
24: * If the request succeeds, the method call will return a model class for
25: * the method you called. This model in turn contains multiple record classes,
26: * each of which represents part of the data returned by the database. If
27: * the database does not contain the requested information, the attributes
28: * on the record class will have a <code>null</code> value.
29: *
30: * If the address is not in the database, an
31: * {@link \GeoIp2\Exception\AddressNotFoundException} exception will be
32: * thrown. If an invalid IP address is passed to one of the methods, a
33: * SPL {@link \InvalidArgumentException} will be thrown. If the database is
34: * corrupt or invalid, a {@link \MaxMind\Db\Reader\InvalidDatabaseException}
35: * will be thrown.
36: *
37: */
38: class Reader implements ProviderInterface
39: {
40: private $dbReader;
41: private $locales;
42:
43: /**
44: * Constructor.
45: *
46: * @param string $filename The path to the GeoIP2 database file.
47: * @param array $locales List of locale codes to use in name property
48: * from most preferred to least preferred.
49: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
50: * is corrupt or invalid
51: */
52: public function __construct(
53: $filename,
54: $locales = array('en')
55: ) {
56: $this->dbReader = new DbReader($filename);
57: $this->locales = $locales;
58: }
59:
60: /**
61: * This method returns a GeoIP2 City model.
62: *
63: * @param string $ipAddress IPv4 or IPv6 address as a string.
64: *
65: * @return \GeoIp2\Model\City
66: *
67: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
68: * not in the database.
69: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
70: * is corrupt or invalid
71: */
72: public function city($ipAddress)
73: {
74: return $this->modelFor('City', 'City', $ipAddress);
75: }
76:
77: /**
78: * This method returns a GeoIP2 Country model.
79: *
80: * @param string $ipAddress IPv4 or IPv6 address as a string.
81: *
82: * @return \GeoIp2\Model\Country
83: *
84: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
85: * not in the database.
86: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
87: * is corrupt or invalid
88: */
89: public function country($ipAddress)
90: {
91: return $this->modelFor('Country', 'Country', $ipAddress);
92: }
93:
94: public function connectionType($ipAddress)
95: {
96: return $this->flatModelFor(
97: 'ConnectionType',
98: 'GeoIP2-Connection-Type',
99: $ipAddress
100: );
101: }
102:
103: public function domain($ipAddress)
104: {
105: return $this->flatModelFor(
106: 'Domain',
107: 'GeoIP2-Domain',
108: $ipAddress
109: );
110: }
111:
112: public function isp($ipAddress)
113: {
114: return $this->flatModelFor(
115: 'Isp',
116: 'GeoIP2-ISP',
117: $ipAddress
118: );
119: }
120:
121: private function modelFor($class, $type, $ipAddress)
122: {
123: $record = $this->getRecord($class, $type, $ipAddress);
124:
125: $record['traits']['ip_address'] = $ipAddress;
126: $class = "GeoIp2\\Model\\" . $class;
127:
128: return new $class($record, $this->locales);
129: }
130:
131: private function flatModelFor($class, $type, $ipAddress)
132: {
133: $record = $this->getRecord($class, $type, $ipAddress);
134:
135: $record['ip_address'] = $ipAddress;
136: $class = "GeoIp2\\Model\\" . $class;
137:
138: return new $class($record);
139: }
140:
141: private function getRecord($class, $type, $ipAddress)
142: {
143: if (strpos($this->metadata()->databaseType, $type) === false) {
144: $method = lcfirst($class);
145: throw new \BadMethodCallException(
146: "The $method method cannot be used to open a "
147: . $this->metadata()->databaseType . " database"
148: );
149: }
150: $record = $this->dbReader->get($ipAddress);
151: if ($record === null) {
152: throw new AddressNotFoundException(
153: "The address $ipAddress is not in the database."
154: );
155: }
156: return $record;
157: }
158:
159: /**
160: * @throws \InvalidArgumentException if arguments are passed to the method.
161: * @throws \BadMethodCallException if the database has been closed.
162: * @return \MaxMind\Db\Reader\Metadata object for the database.
163: */
164: public function metadata()
165: {
166: return $this->dbReader->metadata();
167: }
168:
169: /**
170: * Closes the GeoIP2 database and returns the resources to the system.
171: */
172: public function close()
173: {
174: $this->dbReader->close();
175: }
176: }
177: