Erhan is typing…

WebDevelopment , PHP, Javascript, CakePHP, ExtJS

CakePHP RequestHandler Extended

| Comments

A CakePHP component which extends built-in RequestHandler component by adding some useful geolocation information. It requires MaxMind WebService license key to work properly.

Save it with the name request_handler_ext.php into your application components directory under controllers.

You can call the following methods within your controller (e.g. $this->RequestHandlerExt->methodName()):

Method Returns
getClientCountryCode() ISO 3166 Two-letter Country Code
getClientRegionCode() Region Code
getClientCity() City
getClientPostalCode() Postal Code
getClientLatitude() Latitude
getClientLongitude() Longitude
getClientMetropolitanCode() Metropolitan Code
getClientAreaCode() Area Code
getClientIsp() ISP
getClientOrganization() Organization
request_handler_ext.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
/**
 * Extends RequestHandler component by adding some useful geolocation information.
 * 
 * Requires MaxMind WebService license key to work properly
 *
 * @copyright     2009 Erhan Abay
 * @package       app
 * @subpackage    app.controllers.components
 * @version       $Revision$
 * @lastmodified  $Date$
 */

App::import('Component', 'RequestHandler');

class RequestHandlerExtComponent extends RequestHandlerComponent
{
  /**
  * Required to query MaxMind WebService
  *
  * Provide your own key by replacing XXXXX.
  */
  const MM_LICENSE_KEY = 'XXXXXX';
  
  public function startup(&$controller)
  {
      parent::startup(&$controller);
      $this->controller =& $controller;
  }
  
  /**
  * Searches key value in array returned by function getGeoLocation()
  *
  * @param string $name Name of the method
  * @param unknown_type $arguments Not used, required not to give error
  * @return string if key found
  *         null else
  */
  public function __call($name, $raw = false)
  {
      $var = Inflector::underscore(preg_replace('/getClient/i', '', $name));
      $geo_location = (array)$this->getGeoLocation($raw);
      
      return array_key_exists($var, $geo_location) ? $geo_location[$var] : null;
  }

  /**
  * Queries to the MaxMind WebService and returns an array of information
  *
  * @param bool $raw
  * @return null if IP address is local
  *         bool false if webservice returns error code
  *         string if $raw is set true
  *         array else
  */
  public function getGeoLocation($raw = false)
  {
      if ($this->isLocalIP()) {
          return null;
      }
      
      if ($this->controller->Session->check('User.GeoLocation')) {
          return $raw ? $this->controller->Session->read('User.GeoLocation.raw') : $this->controller->Session->read('User.GeoLocation');
      }
      
    App::import('HttpSocket');

    $http = new HttpSocket();

    /*
     * Returns in order:
     * 
     * 0  ISO 3166 Two-letter Country Code,
     * 1  Region Code,
     * 2  City,
     * 3  Postal Code,
     * 4  Latitude,
     * 5  Longitude,
     * 6  Metropolitan Code,
     * 7  Area Code,
     * 8  ISP,
     * 9  Organization,
     * 10 Error code
     */
    $result = $http->get('http://geoip1.maxmind.com/f', array(
      'l' => self::MM_LICENSE_KEY,
      'i' => $this->getClientIP()
    ));

    $values = explode(',', $result);

    if (isset($values[10])) {
      return false;
    }

    if ($raw) {
      return $result;
    }

    $keys = array('country_code', 'region_code', 'city', 'postal_code', 'latitude', 'longitude', 'metropolitan_code', 'area_code', 'isp', 'organization');
    $data = array_combine($keys, $values);
    $data['coords'] = $values[4].','.$values[5];
    $data['raw'] = $result;
    $this->controller->Session->write('User.GeoLocation', $data);

    return $data;
  }

  /**
   * Detects whether IP address is local or not 
   *
   * @param string $ip IP address to check
   * @return bool
   */
  public function isLocalIP($ip = null) {
      $ip = is_null($ip) ? $this->getClientIP() : $ip;
      
      $regex = '/(192\.168\.[0-9]{1,3}\.[0-9]{1,3})';
      $regex .= '|(10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})';
      $regex .= '|(172\.0?([1][6-9])¦([2][0-9])¦([3][0-1])\.[0-9]{1,3}\.[0-9]{1,3})';
      $regex .= '|(127\.0\.0\.1)/';
      
      return (bool)preg_match($regex, $ip);
  }
}

Comments