1<?php 2 3namespace GeoIp2\Model; 4 5/** 6 * Model class for the data returned by GeoIP2 City web service and database. 7 * 8 * The only difference between the City and Insights model classes is which 9 * fields in each record may be populated. See 10 * http://dev.maxmind.com/geoip/geoip2/web-services more details. 11 * 12 * @property-read \GeoIp2\Record\City $city City data for the requested IP 13 * address. 14 * @property-read \GeoIp2\Record\Continent $continent Continent data for the 15 * requested IP address. 16 * @property-read \GeoIp2\Record\Country $country Country data for the requested 17 * IP address. This object represents the country where MaxMind believes the 18 * end user is located. 19 * @property-read \GeoIp2\Record\Location $location Location data for the 20 * requested IP address. 21 * @property-read \GeoIp2\Record\Postal $postal Postal data for the 22 * requested IP address. 23 * @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind 24 * account. 25 * @property-read \GeoIp2\Record\Country $registeredCountry Registered country 26 * data for the requested IP address. This record represents the country 27 * where the ISP has registered a given IP block and may differ from the 28 * user's country. 29 * @property-read \GeoIp2\Record\RepresentedCountry $representedCountry 30 * Represented country data for the requested IP address. The represented 31 * country is used for things like military bases. It is only present when 32 * the represented country differs from the country. 33 * @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision} 34 * objects representing the country subdivisions for the requested IP 35 * address. The number and type of subdivisions varies by country, but a 36 * subdivision is typically a state, province, county, etc. Subdivisions 37 * are ordered from most general (largest) to most specific (smallest). 38 * If the response did not contain any subdivisions, this method returns 39 * an empty array. 40 * @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An object 41 * representing the most specific subdivision returned. If the response 42 * did not contain any subdivisions, this method returns an empty 43 * {@link \GeoIp2\Record\Subdivision} object. 44 * @property-read \GeoIp2\Record\Traits $traits Data for the traits of the 45 * requested IP address. 46 */ 47class City extends Country 48{ 49 /** 50 * @ignore 51 */ 52 protected $city; 53 /** 54 * @ignore 55 */ 56 protected $location; 57 /** 58 * @ignore 59 */ 60 protected $postal; 61 /** 62 * @ignore 63 */ 64 protected $subdivisions = []; 65 66 /** 67 * @ignore 68 * 69 * @param mixed $raw 70 * @param mixed $locales 71 */ 72 public function __construct($raw, $locales = ['en']) 73 { 74 parent::__construct($raw, $locales); 75 76 $this->city = new \GeoIp2\Record\City($this->get('city'), $locales); 77 $this->location = new \GeoIp2\Record\Location($this->get('location')); 78 $this->postal = new \GeoIp2\Record\Postal($this->get('postal')); 79 80 $this->createSubdivisions($raw, $locales); 81 } 82 83 private function createSubdivisions($raw, $locales) 84 { 85 if (!isset($raw['subdivisions'])) { 86 return; 87 } 88 89 foreach ($raw['subdivisions'] as $sub) { 90 array_push( 91 $this->subdivisions, 92 new \GeoIp2\Record\Subdivision($sub, $locales) 93 ); 94 } 95 } 96 97 /** 98 * @ignore 99 * 100 * @param mixed $attr 101 */ 102 public function __get($attr) 103 { 104 if ($attr === 'mostSpecificSubdivision') { 105 return $this->$attr(); 106 } 107 108 return parent::__get($attr); 109 } 110 111 /** 112 * @ignore 113 * 114 * @param mixed $attr 115 */ 116 public function __isset($attr) 117 { 118 if ($attr === 'mostSpecificSubdivision') { 119 // We always return a mostSpecificSubdivision, even if it is the 120 // empty subdivision 121 return true; 122 } 123 124 return parent::__isset($attr); 125 } 126 127 private function mostSpecificSubdivision() 128 { 129 return empty($this->subdivisions) ? 130 new \GeoIp2\Record\Subdivision([], $this->locales) : 131 end($this->subdivisions); 132 } 133} 134