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 database specific methods.
12: *
13: * ## Usage ##
14: *
15: * The basic API for this class is the same for every database. First, you
16: * create a reader object, specifying a file name. You then call the method
17: * corresponding to the specific database, passing it the IP address you want
18: * to look up.
19: *
20: * If the request succeeds, the method call will return a model class for
21: * the method you called. This model in turn contains multiple record classes,
22: * each of which represents part of the data returned by the database. If
23: * the database does not contain the requested information, the attributes
24: * on the record class will have a `null` value.
25: *
26: * If the address is not in the database, an
27: * {@link \GeoIp2\Exception\AddressNotFoundException} exception will be
28: * thrown. If an invalid IP address is passed to one of the methods, a
29: * SPL {@link \InvalidArgumentException} will be thrown. If the database is
30: * corrupt or invalid, a {@link \MaxMind\Db\Reader\InvalidDatabaseException}
31: * will be thrown.
32: *
33: */
34: class Reader implements ProviderInterface
35: {
36: private $dbReader;
37: private $locales;
38:
39: /**
40: * Constructor.
41: *
42: * @param string $filename The path to the GeoIP2 database file.
43: * @param array $locales List of locale codes to use in name property
44: * from most preferred to least preferred.
45: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
46: * is corrupt or invalid
47: */
48: public function __construct(
49: $filename,
50: $locales = array('en')
51: ) {
52: $this->dbReader = new DbReader($filename);
53: $this->locales = $locales;
54: }
55:
56: /**
57: * This method returns a GeoIP2 City model.
58: *
59: * @param string $ipAddress IPv4 or IPv6 address as a string.
60: *
61: * @return \GeoIp2\Model\City
62: *
63: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
64: * not in the database.
65: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
66: * is corrupt or invalid
67: */
68: public function city($ipAddress)
69: {
70: return $this->modelFor('City', 'City', $ipAddress);
71: }
72:
73: /**
74: * This method returns a GeoIP2 Country model.
75: *
76: * @param string $ipAddress IPv4 or IPv6 address as a string.
77: *
78: * @return \GeoIp2\Model\Country
79: *
80: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
81: * not in the database.
82: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
83: * is corrupt or invalid
84: */
85: public function country($ipAddress)
86: {
87: return $this->modelFor('Country', 'Country', $ipAddress);
88: }
89:
90: /**
91: * This method returns a GeoIP2 Anonymous IP model.
92: *
93: * @param string $ipAddress IPv4 or IPv6 address as a string.
94: *
95: * @return \GeoIp2\Model\AnonymousIp
96: *
97: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
98: * not in the database.
99: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
100: * is corrupt or invalid
101: */
102: public function anonymousIp($ipAddress)
103: {
104: return $this->flatModelFor(
105: 'AnonymousIp',
106: 'GeoIP2-Anonymous-IP',
107: $ipAddress
108: );
109: }
110:
111: /**
112: * This method returns a GeoIP2 Connection Type model.
113: *
114: * @param string $ipAddress IPv4 or IPv6 address as a string.
115: *
116: * @return \GeoIp2\Model\ConnectionType
117: *
118: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
119: * not in the database.
120: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
121: * is corrupt or invalid
122: */
123: public function connectionType($ipAddress)
124: {
125: return $this->flatModelFor(
126: 'ConnectionType',
127: 'GeoIP2-Connection-Type',
128: $ipAddress
129: );
130: }
131:
132: /**
133: * This method returns a GeoIP2 Domain model.
134: *
135: * @param string $ipAddress IPv4 or IPv6 address as a string.
136: *
137: * @return \GeoIp2\Model\Domain
138: *
139: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
140: * not in the database.
141: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
142: * is corrupt or invalid
143: */
144: public function domain($ipAddress)
145: {
146: return $this->flatModelFor(
147: 'Domain',
148: 'GeoIP2-Domain',
149: $ipAddress
150: );
151: }
152:
153: /**
154: * This method returns a GeoIP2 ISP model.
155: *
156: * @param string $ipAddress IPv4 or IPv6 address as a string.
157: *
158: * @return \GeoIp2\Model\Isp
159: *
160: * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
161: * not in the database.
162: * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
163: * is corrupt or invalid
164: */
165: public function isp($ipAddress)
166: {
167: return $this->flatModelFor(
168: 'Isp',
169: 'GeoIP2-ISP',
170: $ipAddress
171: );
172: }
173:
174: private function modelFor($class, $type, $ipAddress)
175: {
176: $record = $this->getRecord($class, $type, $ipAddress);
177:
178: $record['traits']['ip_address'] = $ipAddress;
179: $class = "GeoIp2\\Model\\" . $class;
180:
181: return new $class($record, $this->locales);
182: }
183:
184: private function flatModelFor($class, $type, $ipAddress)
185: {
186: $record = $this->getRecord($class, $type, $ipAddress);
187:
188: $record['ip_address'] = $ipAddress;
189: $class = "GeoIp2\\Model\\" . $class;
190:
191: return new $class($record);
192: }
193:
194: private function getRecord($class, $type, $ipAddress)
195: {
196: if (strpos($this->metadata()->databaseType, $type) === false) {
197: $method = lcfirst($class);
198: throw new \BadMethodCallException(
199: "The $method method cannot be used to open a "
200: . $this->metadata()->databaseType . " database"
201: );
202: }
203: $record = $this->dbReader->get($ipAddress);
204: if ($record === null) {
205: throw new AddressNotFoundException(
206: "The address $ipAddress is not in the database."
207: );
208: }
209: return $record;
210: }
211:
212: /**
213: * @throws \InvalidArgumentException if arguments are passed to the method.
214: * @throws \BadMethodCallException if the database has been closed.
215: * @return \MaxMind\Db\Reader\Metadata object for the database.
216: */
217: public function metadata()
218: {
219: return $this->dbReader->metadata();
220: }
221:
222: /**
223: * Closes the GeoIP2 database and returns the resources to the system.
224: */
225: public function close()
226: {
227: $this->dbReader->close();
228: }
229: }
230: